You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by ar...@apache.org on 2018/04/02 11:31:42 UTC

[01/24] olingo-odata2 git commit: [OLINGO-1253]Client Module for Olingo v2

Repository: olingo-odata2
Updated Branches:
  refs/heads/clientModule 91bd4b897 -> 9e949e406


http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/resources/feed_with_deleted_entries.xml
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/resources/feed_with_deleted_entries.xml b/odata2-lib/odata-client-core/src/test/resources/feed_with_deleted_entries.xml
new file mode 100644
index 0000000..78c187e
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/resources/feed_with_deleted_entries.xml
@@ -0,0 +1,40 @@
+<?xml version='1.0' encoding='utf-8'?>
+<!-- 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. -->
+<feed xmlns="http://www.w3.org/2005/Atom" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"
+    xmlns:at="http://purl.org/atompub/tombstones/1.0" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"
+    xml:base="https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/">
+    <id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Rooms</id>
+    <title type="text">Rooms</title>
+    <updated>2014-01-21T09:15:52.473Z</updated>
+    <author>
+        <name />
+    </author>
+    <link href="Rooms" rel="self" title="Rooms" />
+    <entry m:etag="W/&quot;1&quot;">
+        <id>http://host:123/odata/Rooms('1')</id>
+        <title type="text">Room 1</title>
+        <updated>2014-01-21T09:15:52.474Z</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"
+            title="nr_Employees" type="application/atom+xml;type=feed" />
+        <link href="Rooms('1')/nr_Building" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/nr_Building"
+            title="nr_Building" type="application/atom+xml;type=entry" />
+        <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>
+    <at:deleted-entry ref="http://host:123/odata/Rooms('2')" when="2014-01-14T18:11:06.682+01:00" />
+    <link href="http://host:123/odata/Rooms?$skiptoken=97" rel="delta" />
+</feed>

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/resources/feed_with_delta_link.xml
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/resources/feed_with_delta_link.xml b/odata2-lib/odata-client-core/src/test/resources/feed_with_delta_link.xml
new file mode 100644
index 0000000..bb73341
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/resources/feed_with_delta_link.xml
@@ -0,0 +1,69 @@
+<?xml version='1.0' encoding='utf-8'?>
+<!--
+  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.
+-->
+<feed 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:at="http://purl.org/atompub/tombstones/1.0"
+	xml:base="http://some.host.com/service.root/ReferenceScenario.svc/">
+	<id>http://some.host.com/service.root/ReferenceScenario.svc/Employees</id>
+	<title type="text">Employees</title>
+	<updated>2013-04-23T11:46:14.926Z</updated>
+	<author>
+		<name />
+	</author>
+	<link href="Employees" rel="self" title="Employees" />
+	<entry>
+		<id>http://some.host.com/service.root/ReferenceScenario.svc/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" />
+		<link href="Employees('1')/ne_Manager"
+			rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager"
+			title="ne_Manager" type="application/atom+xml; type=entry" />
+		<link href="Employees('1')/ne_Team"
+			rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team"
+			title="ne_Team" type="application/atom+xml; type=entry" />
+		<link href="Employees('1')/ne_Room"
+			rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room"
+			title="ne_Room" type="application/atom+xml; type=entry" />
+		<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:City m:type="RefScenario.c_City">
+					<d:PostalCode>69124</d:PostalCode>
+					<d:CityName>Heidelberg</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>52</d:Age>
+			<d:EntryDate>1999-01-01T00:00:00</d:EntryDate>
+			<d:ImageUrl>Employees('1')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+	<link href="http://thisisadeltalink" rel="delta"/>
+</feed>

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/resources/metadataForDeepInsert.xml
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/resources/metadataForDeepInsert.xml b/odata2-lib/odata-client-core/src/test/resources/metadataForDeepInsert.xml
new file mode 100644
index 0000000..a718bf5
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/resources/metadataForDeepInsert.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+<edmx:Edmx Version="1.0" xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" >
+	<edmx:DataServices m:DataServiceVersion="2.0">
+		<Schema Namespace="API_PRODUCT_SRV" xml:lang="en"  xmlns="http://schemas.microsoft.com/ado/2008/09/edm">
+			<EntityType Name="A_ProductType" >
+				<Key>
+					<PropertyRef Name="Product"/>
+				</Key>
+				<Property Name="Product" Type="Edm.String" Nullable="false" MaxLength="40" />
+				<Property Name="BaseUnit" Type="Edm.String" MaxLength="3" />
+				<Property Name="ProductType" Type="Edm.String" MaxLength="4"/>
+				<NavigationProperty Name="to_Description" Relationship="API_PRODUCT_SRV.assoc_B3BC21CD74485D381C22EBC58AD5D2F4" FromRole="FromRole_assoc_B3BC21CD74485D381C22EBC58AD5D2F4" ToRole="ToRole_assoc_B3BC21CD74485D381C22EBC58AD5D2F4"/>
+				</EntityType>
+			<EntityType Name="A_ProductDescriptionType" >
+				<Key>
+					<PropertyRef Name="Product"/>
+					<PropertyRef Name="Language"/>
+				</Key>
+				<Property Name="Product" Type="Edm.String" Nullable="false" MaxLength="40" />
+				<Property Name="Language" Type="Edm.String" Nullable="false" MaxLength="2" />
+				<Property Name="ProductDescription" Type="Edm.String" MaxLength="40" />
+			</EntityType>
+			<Association Name="assoc_2754A00DBA9C146B098B85A076E625EE" >
+				<End Type="API_PRODUCT_SRV.A_ProductPlantType" Multiplicity="1" Role="FromRole_assoc_2754A00DBA9C146B098B85A076E625EE"/>
+				<End Type="API_PRODUCT_SRV.A_ProductStorageLocationType" Multiplicity="*" Role="ToRole_assoc_2754A00DBA9C146B098B85A076E625EE"/>
+			</Association>
+			<Association Name="assoc_9E0A9389B585D61EBCFB6C47D388CE0D" >
+				<End Type="API_PRODUCT_SRV.A_ProductType" Multiplicity="1" Role="FromRole_assoc_9E0A9389B585D61EBCFB6C47D388CE0D"/>
+				<End Type="API_PRODUCT_SRV.A_ProductPlantType" Multiplicity="*" Role="ToRole_assoc_9E0A9389B585D61EBCFB6C47D388CE0D"/>
+			</Association>
+			<Association Name="assoc_0D511862D40D30AD11CA2FE43EBDB1DD" >
+				<End Type="API_PRODUCT_SRV.A_ProductType" Multiplicity="1" Role="FromRole_assoc_0D511862D40D30AD11CA2FE43EBDB1DD"/>
+				<End Type="API_PRODUCT_SRV.A_ProductSalesTaxType" Multiplicity="*" Role="ToRole_assoc_0D511862D40D30AD11CA2FE43EBDB1DD"/>
+			</Association>
+			<Association Name="assoc_4AFBA201432776E45B5D3FB9FF74534E" >
+				<End Type="API_PRODUCT_SRV.A_ProductType" Multiplicity="1" Role="FromRole_assoc_4AFBA201432776E45B5D3FB9FF74534E"/>
+				<End Type="API_PRODUCT_SRV.A_ProductSalesDeliveryType" Multiplicity="*" Role="ToRole_assoc_4AFBA201432776E45B5D3FB9FF74534E"/>
+			</Association>
+			<Association Name="assoc_B3BC21CD74485D381C22EBC58AD5D2F4" >
+				<End Type="API_PRODUCT_SRV.A_ProductType" Multiplicity="1" Role="FromRole_assoc_B3BC21CD74485D381C22EBC58AD5D2F4"/>
+				<End Type="API_PRODUCT_SRV.A_ProductDescriptionType" Multiplicity="*" Role="ToRole_assoc_B3BC21CD74485D381C22EBC58AD5D2F4"/>
+			</Association>
+			<EntityContainer Name="API_PRODUCT_SRV_Entities" m:IsDefaultEntityContainer="true" >
+				<EntitySet Name="A_Product" EntityType="API_PRODUCT_SRV.A_ProductType" />
+				<EntitySet Name="A_ProductDescription" EntityType="API_PRODUCT_SRV.A_ProductDescriptionType" />
+				<AssociationSet Name="assoc_B3BC21CD74485D381C22EBC58AD5D2F4" Association="API_PRODUCT_SRV.assoc_B3BC21CD74485D381C22EBC58AD5D2F4" >
+					<End EntitySet="A_Product" Role="FromRole_assoc_B3BC21CD74485D381C22EBC58AD5D2F4"/>
+					<End EntitySet="A_ProductDescription" Role="ToRole_assoc_B3BC21CD74485D381C22EBC58AD5D2F4"/>
+				</AssociationSet>
+			</EntityContainer>
+		</Schema>
+	</edmx:DataServices>
+</edmx:Edmx>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/resources/metadataForRelatedEntity.xml
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/resources/metadataForRelatedEntity.xml b/odata2-lib/odata-client-core/src/test/resources/metadataForRelatedEntity.xml
new file mode 100644
index 0000000..2a5ee89
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/resources/metadataForRelatedEntity.xml
@@ -0,0 +1,240 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<edmx:Edmx Version="1.0" xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns:sap="http://www.sap.com/Protocols/SAPData">
+	<edmx:DataServices m:DataServiceVersion="2.0">
+		<Schema Namespace="CUAN_BUSINESS_DOCUMENT_IMP_SRV" xml:lang="en" sap:schema-version="1" xmlns="http://schemas.microsoft.com/ado/2008/09/edm">
+			<EntityType Name="ImportHeader" sap:content-version="1">
+				<Key>
+					<PropertyRef Name="Id"/>
+				</Key>
+				<Property Name="Id" Type="Edm.String" Nullable="false" MaxLength="32" sap:label="ID" sap:updatable="false"/>
+				<Property Name="Timestamp" Type="Edm.DateTime" Precision="7" sap:label="Timestamp" sap:updatable="false"/>
+				<Property Name="SourceSystemType" Type="Edm.String" MaxLength="20" sap:label="Source System Type" sap:updatable="false"/>
+				<Property Name="SourceSystemId" Type="Edm.String" MaxLength="20" sap:label="Source System ID" sap:updatable="false"/>
+				<NavigationProperty Name="BusinessDocuments" Relationship="CUAN_BUSINESS_DOCUMENT_IMP_SRV.HeaderBusinessDocument" FromRole="FromRole_HeaderBusinessDocument" ToRole="ToRole_HeaderBusinessDocument" sap:label="Business Documents"/>
+			</EntityType>
+			<EntityType Name="BusinessDocument" sap:content-version="1">
+				<Key>
+					<PropertyRef Name="Id"/>
+				</Key>
+				<Property Name="Id" Type="Edm.String" Nullable="false" MaxLength="32" sap:label="Key" sap:updatable="false"/>
+				<Property Name="ContactIdOrigin" Type="Edm.String" MaxLength="20" sap:label="Contact ID Origin" sap:updatable="false"/>
+				<Property Name="ContactId" Type="Edm.String" MaxLength="255" sap:label="Contact ID" sap:updatable="false"/>
+				<Property Name="InternalContactId" Type="Edm.String" MaxLength="255" sap:label="Internal Contact ID" sap:updatable="false"/>
+				<Property Name="InternalObjectType" Type="Edm.String" MaxLength="20" sap:label="Business Document Type" sap:updatable="false"/>
+				<Property Name="ExternalObjectType" Type="Edm.String" MaxLength="30" sap:label="Internal Object Type" sap:updatable="false"/>
+				<Property Name="ExternalId" Type="Edm.String" MaxLength="50" sap:label="External Id" sap:updatable="false"/>
+				<Property Name="ExternalStatusCode" Type="Edm.String" MaxLength="2" sap:label="Status Code" sap:updatable="false"/>
+				<Property Name="ExternalTimeStamp" Type="Edm.DateTime" Precision="7" sap:label="External Time Stamp" sap:updatable="false"/>
+				<Property Name="Content" Type="Edm.String" sap:label="Business Document Content" sap:updatable="false" sap:sortable="false"/>
+				<Property Name="ExpectedRevenue" Type="Edm.Decimal" Precision="31" Scale="2" sap:unit="Currency" sap:label="Expected Revenue" sap:updatable="false"/>
+				<Property Name="Currency" Type="Edm.String" MaxLength="5" sap:label="Currency" sap:updatable="false" sap:semantics="currency-code"/>
+				<Property Name="PredecessorId" Type="Edm.String" MaxLength="50" sap:label="Predecessor Id" sap:updatable="false"/>
+				<Property Name="ActionCode" Type="Edm.String" MaxLength="2" sap:label="Action Code" sap:updatable="false"/>
+				<Property Name="ContentTitle" Type="Edm.String" MaxLength="255" sap:label="Content Title" sap:updatable="false"/>
+				<Property Name="EndTimeStamp" Type="Edm.DateTime" Precision="7" sap:label="End Timestamp" sap:updatable="false"/>
+				<Property Name="Reason" Type="Edm.String" MaxLength="20" sap:label="Reason" sap:updatable="false"/>
+				<Property Name="ExternalAdditionalId" Type="Edm.String" MaxLength="50" sap:label="External Additional ID" sap:updatable="false"/>
+				<Property Name="Amount" Type="Edm.Decimal" Precision="31" Scale="2" sap:unit="Currency" sap:label="Expected Revenue" sap:updatable="false"/>
+				<Property Name="Boolean1" Type="Edm.Boolean" sap:label="TRUE" sap:is-extension-field="true"/>
+				<Property Name="Boolean2" Type="Edm.Boolean" sap:label="TRUE" sap:is-extension-field="true"/>
+				<Property Name="Boolean3" Type="Edm.Boolean" sap:label="TRUE" sap:is-extension-field="true"/>
+				<Property Name="Boolean4" Type="Edm.Boolean" sap:label="TRUE" sap:is-extension-field="true"/>
+				<Property Name="Date3" Type="Edm.DateTime" Precision="0" sap:display-format="Date" sap:label="Date" sap:is-extension-field="true"/>
+				<Property Name="Number1" Type="Edm.Int32" sap:label="INT4" sap:is-extension-field="true"/>
+				<Property Name="Number2" Type="Edm.Int32" sap:label="INT4" sap:is-extension-field="true"/>
+				<Property Name="Text201" Type="Edm.String" MaxLength="20" sap:label="Text" sap:is-extension-field="true"/>
+				<Property Name="Text202" Type="Edm.String" MaxLength="20" sap:label="Text" sap:is-extension-field="true"/>
+				<Property Name="Decimal1" Type="Edm.Decimal" Precision="25" Scale="2" sap:label="Decimal Value" sap:is-extension-field="true"/>
+				<Property Name="Text401" Type="Edm.String" MaxLength="40" sap:label="Text" sap:is-extension-field="true"/>
+				<Property Name="Text402" Type="Edm.String" MaxLength="40" sap:label="Text" sap:is-extension-field="true"/>
+				<Property Name="Text801" Type="Edm.String" MaxLength="80" sap:label="Text" sap:is-extension-field="true"/>
+				<Property Name="Text802" Type="Edm.String" MaxLength="80" sap:label="Text" sap:is-extension-field="true"/>
+				<Property Name="Text1201" Type="Edm.String" MaxLength="120" sap:label="Text" sap:is-extension-field="true"/>
+				<Property Name="Text1202" Type="Edm.String" MaxLength="120" sap:label="Text" sap:is-extension-field="true"/>
+				<Property Name="Text2551" Type="Edm.String" MaxLength="255" sap:label="Text" sap:is-extension-field="true"/>
+				<NavigationProperty Name="ProductItems" Relationship="CUAN_BUSINESS_DOCUMENT_IMP_SRV.BusinessDocumentProductItem" FromRole="FromRole_BusinessDocumentProductItem" ToRole="ToRole_BusinessDocumentProductItem"/>
+				<NavigationProperty Name="Offers" Relationship="CUAN_BUSINESS_DOCUMENT_IMP_SRV.BusinessDocumentOffer" FromRole="FromRole_BusinessDocumentOffer" ToRole="ToRole_BusinessDocumentOffer" sap:label="Offers"/>
+				<NavigationProperty Name="AdditionalObjectReferences" Relationship="CUAN_BUSINESS_DOCUMENT_IMP_SRV.BusinessDocumentAdditionalObjectRef" FromRole="FromRole_BusinessDocumentAdditionalObjectRef" ToRole="ToRole_BusinessDocumentAdditionalObjectRef" sap:label="Additional Object References"/>
+				<NavigationProperty Name="Person" Relationship="CUAN_BUSINESS_DOCUMENT_IMP_SRV.BusinessDocumentPerson" FromRole="FromRole_BusinessDocumentPerson" ToRole="ToRole_BusinessDocumentPerson"/>
+				<NavigationProperty Name="Company" Relationship="CUAN_BUSINESS_DOCUMENT_IMP_SRV.BusinessDocumentCompany" FromRole="FromRole_BusinessDocumentCompany" ToRole="ToRole_BusinessDocumentCompany"/>
+			</EntityType>
+			<EntityType Name="Company" sap:content-version="1">
+				<Key>
+					<PropertyRef Name="Id"/>
+					<PropertyRef Name="IdOrigin"/>
+				</Key>
+				<Property Name="Id" Type="Edm.String" Nullable="false" MaxLength="100" sap:label="Company ID"/>
+				<Property Name="IdOrigin" Type="Edm.String" Nullable="false" MaxLength="20" sap:label="Company ID Origin"/>
+				<Property Name="InternalId" Type="Edm.String" Nullable="false" MaxLength="100" sap:label="yMKT Company ID"/>
+				<Property Name="LastChangeDate" Type="Edm.DateTime" Nullable="false" Precision="7" sap:label="Last Change Date"/>
+				<Property Name="CompanyName" Type="Edm.String" MaxLength="80" sap:label="Name"/>
+				<Property Name="CountryCode" Type="Edm.String" MaxLength="3" sap:label="Country Code"/>
+				<Property Name="RegionCode" Type="Edm.String" MaxLength="3" sap:label="Region Code"/>
+				<Property Name="CityName" Type="Edm.String" MaxLength="40" sap:label="City Name"/>
+				<Property Name="PostalCode" Type="Edm.String" MaxLength="10" sap:label="Postal Code"/>
+				<Property Name="Street" Type="Edm.String" MaxLength="60" sap:label="Street"/>
+				<Property Name="HouseNumber" Type="Edm.String" MaxLength="10" sap:label="House Number"/>
+				<Property Name="EmailAddress" Type="Edm.String" MaxLength="241" sap:label="Email Address"/>
+				<Property Name="PhoneNumber" Type="Edm.String" MaxLength="30" sap:label="Phone Number"/>
+				<Property Name="FaxNumber" Type="Edm.String" MaxLength="30" sap:label="Fax Number"/>
+				<Property Name="WebSite" Type="Edm.String" MaxLength="1000" sap:label="Web URI"/>
+				<Property Name="IndustryCode" Type="Edm.String" MaxLength="4" sap:label="Industry Code"/>
+				<Property Name="LanguageCode" Type="Edm.String" MaxLength="2" sap:label="Preferred Language Code"/>
+				<Property Name="Date2" Type="Edm.DateTime" Precision="0" sap:display-format="Date" sap:label="Date" sap:is-extension-field="true"/>
+				<Property Name="Date3" Type="Edm.DateTime" Precision="0" sap:display-format="Date" sap:label="Date" sap:is-extension-field="true"/>
+				<Property Name="Number3" Type="Edm.Int32" sap:label="INT4" sap:is-extension-field="true"/>
+				<Property Name="Text202" Type="Edm.String" MaxLength="20" sap:label="Description" sap:is-extension-field="true"/>
+				<Property Name="Text402" Type="Edm.String" MaxLength="40" sap:label="Text, 40 Characters Long" sap:is-extension-field="true"/>
+				<Property Name="Text1201" Type="Edm.String" MaxLength="120" sap:label="Text (Length 120)" sap:is-extension-field="true"/>
+			</EntityType>
+			<EntityType Name="Person" sap:content-version="1">
+				<Key>
+					<PropertyRef Name="Id"/>
+					<PropertyRef Name="IdOrigin"/>
+				</Key>
+				<Property Name="Id" Type="Edm.String" Nullable="false" MaxLength="100" sap:label="Company ID"/>
+				<Property Name="IdOrigin" Type="Edm.String" Nullable="false" MaxLength="20" sap:label="Company ID Origin"/>
+				<Property Name="InternalId" Type="Edm.String" Nullable="false" MaxLength="100" sap:label="Internal Company Id"/>
+				<Property Name="LastChangeDate" Type="Edm.DateTime" Nullable="false" Precision="7" sap:label="Last Change Date"/>
+				<Property Name="FirstName" Type="Edm.String" MaxLength="40" sap:label="First Name"/>
+				<Property Name="LastName" Type="Edm.String" MaxLength="40" sap:label="Last Name"/>
+				<Property Name="FullName" Type="Edm.String" MaxLength="80" sap:label="Full Name"/>
+				<Property Name="DateOfBirth" Type="Edm.DateTime" Precision="0" sap:display-format="Date" sap:label="Date of Birth"/>
+				<Property Name="GenderCode" Type="Edm.String" MaxLength="1" sap:label="Gender Code"/>
+				<Property Name="MaritalStatusCode" Type="Edm.String" MaxLength="1" sap:label="Marital Status Code"/>
+				<Property Name="TitleCode" Type="Edm.String" MaxLength="4" sap:label="Title Code"/>
+				<Property Name="CountryCode" Type="Edm.String" MaxLength="3" sap:label="Country Code"/>
+				<Property Name="RegionCode" Type="Edm.String" MaxLength="3" sap:label="Region Code"/>
+				<Property Name="CityName" Type="Edm.String" MaxLength="40" sap:label="City Name"/>
+				<Property Name="PostalCode" Type="Edm.String" MaxLength="10" sap:label="Postal Code"/>
+				<Property Name="Street" Type="Edm.String" MaxLength="60" sap:label="Street"/>
+				<Property Name="HouseNumber" Type="Edm.String" MaxLength="10" sap:label="House Number"/>
+				<Property Name="EmailAddress" Type="Edm.String" MaxLength="241" sap:label="Email Address"/>
+				<Property Name="PhoneNumber" Type="Edm.String" MaxLength="30" sap:label="Phone Number"/>
+				<Property Name="MobilePhoneNumber" Type="Edm.String" MaxLength="30" sap:label="Mobile Phone Number"/>
+				<Property Name="FaxNumber" Type="Edm.String" MaxLength="30" sap:label="Fax Number"/>
+				<Property Name="WebSite" Type="Edm.String" MaxLength="1000" sap:label="Web URI"/>
+				<Property Name="IsConsumer" Type="Edm.Boolean" sap:label="Person is Consumer"/>
+				<Property Name="IsContact" Type="Edm.Boolean" sap:label="Person is Contact"/>
+				<Property Name="LanguageCode" Type="Edm.String" MaxLength="2" sap:label="Preferred Language"/>
+				<Property Name="Boolean1" Type="Edm.Boolean" sap:label="TRUE" sap:is-extension-field="true"/>
+				<Property Name="Boolean2" Type="Edm.Boolean" sap:label="TRUE" sap:is-extension-field="true"/>
+				<Property Name="Boolean3" Type="Edm.Boolean" sap:label="TRUE" sap:is-extension-field="true"/>
+				<Property Name="Boolean4" Type="Edm.Boolean" sap:label="TRUE" sap:is-extension-field="true"/>
+				<Property Name="Time1" Type="Edm.Time" Precision="0" sap:label="Field of type TIMS" sap:is-extension-field="true"/>
+				<Property Name="Date1" Type="Edm.DateTime" Precision="0" sap:display-format="Date" sap:label="Date" sap:is-extension-field="true"/>
+				<Property Name="Number1" Type="Edm.Int32" sap:label="INT4" sap:is-extension-field="true"/>
+				<Property Name="Number2" Type="Edm.Int32" sap:label="INT4" sap:is-extension-field="true"/>
+				<Property Name="Text201" Type="Edm.String" MaxLength="20" sap:label="Description" sap:is-extension-field="true"/>
+				<Property Name="Text203" Type="Edm.String" MaxLength="20" sap:label="Description" sap:is-extension-field="true"/>
+				<Property Name="Timestamp1" Type="Edm.DateTime" Precision="7" sap:label="Time Stamp" sap:is-extension-field="true"/>
+				<Property Name="Timestamp2" Type="Edm.DateTime" Precision="7" sap:label="Time Stamp" sap:is-extension-field="true"/>
+				<Property Name="Decimal1" Type="Edm.Decimal" Precision="25" Scale="2" sap:label="Decimal Value" sap:is-extension-field="true"/>
+				<Property Name="Decimal2" Type="Edm.Decimal" Precision="25" Scale="2" sap:label="Decimal Value" sap:is-extension-field="true"/>
+				<Property Name="Decimal3" Type="Edm.Decimal" Precision="25" Scale="2" sap:label="Decimal Value" sap:is-extension-field="true"/>
+				<Property Name="Text401" Type="Edm.String" MaxLength="40" sap:label="Text, 40 Characters Long" sap:is-extension-field="true"/>
+				<Property Name="Text403" Type="Edm.String" MaxLength="40" sap:label="Text, 40 Characters Long" sap:is-extension-field="true"/>
+				<Property Name="Text801" Type="Edm.String" MaxLength="80" sap:label="Text" sap:is-extension-field="true"/>
+				<Property Name="Text802" Type="Edm.String" MaxLength="80" sap:label="Text" sap:is-extension-field="true"/>
+				<Property Name="Text803" Type="Edm.String" MaxLength="80" sap:label="Text" sap:is-extension-field="true"/>
+				<Property Name="Text1202" Type="Edm.String" MaxLength="120" sap:label="Text (Length 120)" sap:is-extension-field="true"/>
+				<Property Name="Text1203" Type="Edm.String" MaxLength="120" sap:label="Text (Length 120)" sap:is-extension-field="true"/>
+				<Property Name="Text2551" Type="Edm.String" MaxLength="255" sap:label="Text" sap:is-extension-field="true"/>
+				<Property Name="Text2552" Type="Edm.String" MaxLength="255" sap:label="Text" sap:is-extension-field="true"/>
+			</EntityType>
+			<EntityType Name="ProductItem" sap:content-version="1">
+				<Key>
+					<PropertyRef Name="Id"/>
+					<PropertyRef Name="ObjectType"/>
+				</Key>
+				<Property Name="Id" Type="Edm.String" Nullable="false" MaxLength="32" sap:label="ID" sap:updatable="false"/>
+				<Property Name="ObjectType" Type="Edm.String" Nullable="false" MaxLength="30" sap:label="Origin of Product" sap:updatable="false"/>
+				<Property Name="ObjectId" Type="Edm.String" Nullable="false" MaxLength="50" sap:label="Product ID" sap:updatable="false"/>
+				<Property Name="ProductName" Type="Edm.String" MaxLength="40" sap:label="Product" sap:updatable="false"/>
+				<Property Name="ProductDesc" Type="Edm.String" MaxLength="512" sap:label="Product Desc." sap:updatable="false"/>
+				<Property Name="Amount" Type="Edm.Decimal" Precision="31" Scale="2" sap:label="Amount" sap:updatable="false"/>
+				<Property Name="Quantity" Type="Edm.Decimal" Precision="22" Scale="5" sap:unit="UnitOfMeasure" sap:label="Quantity" sap:updatable="false"/>
+				<Property Name="UnitOfMeasure" Type="Edm.String" MaxLength="3" sap:label="Unit of Measure" sap:updatable="false"/>
+				<Property Name="Boolean1" Type="Edm.Boolean" sap:label="Boolean" sap:is-extension-field="true"/>
+				<Property Name="Amount1" Type="Edm.Decimal" Precision="31" Scale="2" sap:unit="PC41DED6CC4BCDED781F75143862C189C" sap:label="Amount" sap:is-extension-field="true"/>
+			</EntityType>
+			<EntityType Name="AdditionalObjectReference" sap:content-version="1">
+				<Key>
+					<PropertyRef Name="ObjectType"/>
+					<PropertyRef Name="ObjectId"/>
+				</Key>
+				<Property Name="ObjectType" Type="Edm.String" Nullable="false" MaxLength="30" sap:label="Object Type" sap:updatable="false"/>
+				<Property Name="ObjectId" Type="Edm.String" Nullable="false" MaxLength="50" sap:label="Object ID" sap:updatable="false"/>
+			</EntityType>
+			<EntityType Name="Offer" sap:content-version="1">
+				<Key>
+					<PropertyRef Name="Origin"/>
+					<PropertyRef Name="Id"/>
+				</Key>
+				<Property Name="Origin" Type="Edm.String" Nullable="false" MaxLength="30" sap:label="Origin" sap:updatable="false"/>
+				<Property Name="Id" Type="Edm.String" Nullable="false" MaxLength="10" sap:label="ID" sap:updatable="false"/>
+				<Property Name="ContentItemId" Type="Edm.String" MaxLength="5" sap:label="Content Item No." sap:updatable="false"/>
+				<Property Name="RecommendationScenarioId" Type="Edm.String" MaxLength="50" sap:label="Scenario ID" sap:updatable="false"/>
+			</EntityType>
+			<Association Name="BusinessDocumentCompany" sap:content-version="1">
+				<End Type="CUAN_BUSINESS_DOCUMENT_IMP_SRV.BusinessDocument" Multiplicity="1" Role="FromRole_BusinessDocumentCompany"/>
+				<End Type="CUAN_BUSINESS_DOCUMENT_IMP_SRV.Company" Multiplicity="0..1" Role="ToRole_BusinessDocumentCompany"/>
+			</Association>
+			<Association Name="BusinessDocumentPerson" sap:content-version="1">
+				<End Type="CUAN_BUSINESS_DOCUMENT_IMP_SRV.BusinessDocument" Multiplicity="1" Role="FromRole_BusinessDocumentPerson"/>
+				<End Type="CUAN_BUSINESS_DOCUMENT_IMP_SRV.Person" Multiplicity="0..1" Role="ToRole_BusinessDocumentPerson"/>
+			</Association>
+			<Association Name="BusinessDocumentAdditionalObjectRef" sap:content-version="1">
+				<End Type="CUAN_BUSINESS_DOCUMENT_IMP_SRV.BusinessDocument" Multiplicity="1" Role="FromRole_BusinessDocumentAdditionalObjectRef"/>
+				<End Type="CUAN_BUSINESS_DOCUMENT_IMP_SRV.AdditionalObjectReference" Multiplicity="*" Role="ToRole_BusinessDocumentAdditionalObjectRef"/>
+			</Association>
+			<Association Name="BusinessDocumentOffer" sap:content-version="1">
+				<End Type="CUAN_BUSINESS_DOCUMENT_IMP_SRV.BusinessDocument" Multiplicity="1" Role="FromRole_BusinessDocumentOffer"/>
+				<End Type="CUAN_BUSINESS_DOCUMENT_IMP_SRV.Offer" Multiplicity="*" Role="ToRole_BusinessDocumentOffer"/>
+			</Association>
+			<Association Name="BusinessDocumentProductItem" sap:content-version="1">
+				<End Type="CUAN_BUSINESS_DOCUMENT_IMP_SRV.BusinessDocument" Multiplicity="1" Role="FromRole_BusinessDocumentProductItem"/>
+				<End Type="CUAN_BUSINESS_DOCUMENT_IMP_SRV.ProductItem" Multiplicity="*" Role="ToRole_BusinessDocumentProductItem"/>
+			</Association>
+			<Association Name="HeaderBusinessDocument" sap:content-version="1">
+				<End Type="CUAN_BUSINESS_DOCUMENT_IMP_SRV.ImportHeader" Multiplicity="1" Role="FromRole_HeaderBusinessDocument"/>
+				<End Type="CUAN_BUSINESS_DOCUMENT_IMP_SRV.BusinessDocument" Multiplicity="*" Role="ToRole_HeaderBusinessDocument"/>
+			</Association>
+			<EntityContainer Name="CUAN_BUSINESS_DOCUMENT_IMP_SRV_Entities" m:IsDefaultEntityContainer="true" sap:supported-formats="atom json xlsx">
+				<EntitySet Name="ImportHeaders" EntityType="CUAN_BUSINESS_DOCUMENT_IMP_SRV.ImportHeader" sap:updatable="false" sap:deletable="false" sap:pageable="false" sap:addressable="false" sap:content-version="1"/>
+				<EntitySet Name="BusinessDocuments" EntityType="CUAN_BUSINESS_DOCUMENT_IMP_SRV.BusinessDocument" sap:updatable="false" sap:deletable="false" sap:pageable="false" sap:addressable="false" sap:content-version="1"/>
+				<EntitySet Name="Companies" EntityType="CUAN_BUSINESS_DOCUMENT_IMP_SRV.Company" sap:updatable="false" sap:deletable="false" sap:pageable="false" sap:addressable="false" sap:content-version="1"/>
+				<EntitySet Name="Persons" EntityType="CUAN_BUSINESS_DOCUMENT_IMP_SRV.Person" sap:updatable="false" sap:deletable="false" sap:pageable="false" sap:addressable="false" sap:content-version="1"/>
+				<EntitySet Name="ProductItems" EntityType="CUAN_BUSINESS_DOCUMENT_IMP_SRV.ProductItem" sap:updatable="false" sap:deletable="false" sap:pageable="false" sap:addressable="false" sap:content-version="1"/>
+				<EntitySet Name="AdditionalObjectReferences" EntityType="CUAN_BUSINESS_DOCUMENT_IMP_SRV.AdditionalObjectReference" sap:updatable="false" sap:deletable="false" sap:pageable="false" sap:addressable="false" sap:content-version="1"/>
+				<EntitySet Name="Offers" EntityType="CUAN_BUSINESS_DOCUMENT_IMP_SRV.Offer" sap:updatable="false" sap:deletable="false" sap:pageable="false" sap:addressable="false" sap:content-version="1"/>
+				<AssociationSet Name="BusinessDocumentOffer_AssocSet" Association="CUAN_BUSINESS_DOCUMENT_IMP_SRV.BusinessDocumentOffer" sap:creatable="false" sap:updatable="false" sap:deletable="false" sap:content-version="1">
+					<End EntitySet="BusinessDocuments" Role="FromRole_BusinessDocumentOffer"/>
+					<End EntitySet="Offers" Role="ToRole_BusinessDocumentOffer"/>
+				</AssociationSet>
+				<AssociationSet Name="BusinessDocumentProductItems" Association="CUAN_BUSINESS_DOCUMENT_IMP_SRV.BusinessDocumentProductItem" sap:creatable="false" sap:updatable="false" sap:deletable="false" sap:content-version="1">
+					<End EntitySet="BusinessDocuments" Role="FromRole_BusinessDocumentProductItem"/>
+					<End EntitySet="ProductItems" Role="ToRole_BusinessDocumentProductItem"/>
+				</AssociationSet>
+				<AssociationSet Name="BusinessDocumentCompany_AssocSet" Association="CUAN_BUSINESS_DOCUMENT_IMP_SRV.BusinessDocumentCompany" sap:creatable="false" sap:updatable="false" sap:deletable="false" sap:content-version="1">
+					<End EntitySet="BusinessDocuments" Role="FromRole_BusinessDocumentCompany"/>
+					<End EntitySet="Companies" Role="ToRole_BusinessDocumentCompany"/>
+				</AssociationSet>
+				<AssociationSet Name="BusinessDocumentAdditionalObjectRef_Asso" Association="CUAN_BUSINESS_DOCUMENT_IMP_SRV.BusinessDocumentAdditionalObjectRef" sap:creatable="false" sap:updatable="false" sap:deletable="false" sap:content-version="1">
+					<End EntitySet="BusinessDocuments" Role="FromRole_BusinessDocumentAdditionalObjectRef"/>
+					<End EntitySet="AdditionalObjectReferences" Role="ToRole_BusinessDocumentAdditionalObjectRef"/>
+				</AssociationSet>
+				<AssociationSet Name="BusinessDocumentPerson_AssocSet" Association="CUAN_BUSINESS_DOCUMENT_IMP_SRV.BusinessDocumentPerson" sap:creatable="false" sap:updatable="false" sap:deletable="false" sap:content-version="1">
+					<End EntitySet="BusinessDocuments" Role="FromRole_BusinessDocumentPerson"/>
+					<End EntitySet="Persons" Role="ToRole_BusinessDocumentPerson"/>
+				</AssociationSet>
+				<AssociationSet Name="HeaderBusinessDocument_AssocSet" Association="CUAN_BUSINESS_DOCUMENT_IMP_SRV.HeaderBusinessDocument" sap:creatable="false" sap:updatable="false" sap:deletable="false" sap:content-version="1">
+					<End EntitySet="ImportHeaders" Role="FromRole_HeaderBusinessDocument"/>
+					<End EntitySet="BusinessDocuments" Role="ToRole_HeaderBusinessDocument"/>
+				</AssociationSet>
+			</EntityContainer>
+			<atom:link rel="self" href="https://ldciana.wdf.sap.corp:44300/sap/opu/odata/sap/CUAN_BUSINESS_DOCUMENT_IMP_SRV/$metadata" xmlns:atom="http://www.w3.org/2005/Atom"/>
+			<atom:link rel="latest-version" href="https://ldciana.wdf.sap.corp:44300/sap/opu/odata/sap/CUAN_BUSINESS_DOCUMENT_IMP_SRV/$metadata" xmlns:atom="http://www.w3.org/2005/Atom"/>
+		</Schema>
+	</edmx:DataServices>
+</edmx:Edmx>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/resources/metadataProducts.xml
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/resources/metadataProducts.xml b/odata2-lib/odata-client-core/src/test/resources/metadataProducts.xml
new file mode 100644
index 0000000..0a10a93
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/resources/metadataProducts.xml
@@ -0,0 +1,69 @@
+<edmx:Edmx xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx" Version="1.0">
+	<edmx:DataServices xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" m:DataServiceVersion="2.0">
+		<Schema xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns="http://schemas.microsoft.com/ado/2007/05/edm" Namespace="ODataDemo">
+			<EntityType Name="Product">
+				<Key>
+					<PropertyRef Name="ID"/>
+				</Key>
+				<Property Name="ID" Type="Edm.Int32" Nullable="false"/>
+				<Property Name="Name" Type="Edm.String" Nullable="true" m:FC_TargetPath="SyndicationTitle" m:FC_ContentKind="text" m:FC_KeepInContent="false"/>
+				<Property Name="Description" Type="Edm.String" Nullable="true" m:FC_TargetPath="SyndicationSummary" m:FC_ContentKind="text" m:FC_KeepInContent="false"/>
+				<Property Name="ReleaseDate" Type="Edm.DateTime" Nullable="false"/>
+				<Property Name="DiscontinuedDate" Type="Edm.DateTime" Nullable="true"/>
+				<Property Name="Rating" Type="Edm.Int32" Nullable="false"/>
+				<Property Name="Price" Type="Edm.Decimal" Nullable="false"/>
+				<NavigationProperty Name="Category" Relationship="ODataDemo.Product_Category_Category_Products" FromRole="Product_Category" ToRole="Category_Products"/>
+				<NavigationProperty Name="Supplier" Relationship="ODataDemo.Product_Supplier_Supplier_Products" FromRole="Product_Supplier" ToRole="Supplier_Products"/>
+			</EntityType>
+			<EntityType Name="Category">
+				<Key>
+					<PropertyRef Name="ID"/>
+				</Key>
+				<Property Name="ID" Type="Edm.Int32" Nullable="false"/>
+				<Property Name="Name" Type="Edm.String" Nullable="true" m:FC_TargetPath="SyndicationTitle" m:FC_ContentKind="text" m:FC_KeepInContent="true"/>
+				<NavigationProperty Name="Products" Relationship="ODataDemo.Product_Category_Category_Products" FromRole="Category_Products" ToRole="Product_Category"/>
+			</EntityType>
+			<EntityType Name="Supplier">
+				<Key>
+					<PropertyRef Name="ID"/>
+				</Key>
+				<Property Name="ID" Type="Edm.Int32" Nullable="false"/>
+				<Property Name="Name" Type="Edm.String" Nullable="true" m:FC_TargetPath="SyndicationTitle" m:FC_ContentKind="text" m:FC_KeepInContent="true"/>
+				<Property Name="Address" Type="ODataDemo.Address" Nullable="false"/>
+				<Property Name="Concurrency" Type="Edm.Int32" Nullable="false" ConcurrencyMode="Fixed"/>
+				<NavigationProperty Name="Products" Relationship="ODataDemo.Product_Supplier_Supplier_Products" FromRole="Supplier_Products" ToRole="Product_Supplier"/>
+			</EntityType>
+			<ComplexType Name="Address">
+				<Property Name="Street" Type="Edm.String" Nullable="true"/>
+				<Property Name="City" Type="Edm.String" Nullable="true"/>
+				<Property Name="State" Type="Edm.String" Nullable="true"/>
+				<Property Name="ZipCode" Type="Edm.String" Nullable="true"/>
+				<Property Name="Country" Type="Edm.String" Nullable="true"/>
+			</ComplexType>
+			<Association Name="Product_Category_Category_Products">
+				<End Role="Product_Category" Type="ODataDemo.Product" Multiplicity="*"/>
+				<End Role="Category_Products" Type="ODataDemo.Category" Multiplicity="0..1"/>
+			</Association>
+			<Association Name="Product_Supplier_Supplier_Products">
+				<End Role="Product_Supplier" Type="ODataDemo.Product" Multiplicity="*"/>
+				<End Role="Supplier_Products" Type="ODataDemo.Supplier" Multiplicity="0..1"/>
+			</Association>
+			<EntityContainer Name="DemoService" m:IsDefaultEntityContainer="true">
+				<EntitySet Name="Products" EntityType="ODataDemo.Product"/>
+				<EntitySet Name="Categories" EntityType="ODataDemo.Category"/>
+				<EntitySet Name="Suppliers" EntityType="ODataDemo.Supplier"/>
+				<AssociationSet Name="Products_Category_Categories" Association="ODataDemo.Product_Category_Category_Products">
+					<End Role="Product_Category" EntitySet="Products"/>
+					<End Role="Category_Products" EntitySet="Categories"/>
+				</AssociationSet>
+				<AssociationSet Name="Products_Supplier_Suppliers" Association="ODataDemo.Product_Supplier_Supplier_Products">
+					<End Role="Product_Supplier" EntitySet="Products"/>
+					<End Role="Supplier_Products" EntitySet="Suppliers"/>
+				</AssociationSet>
+				<FunctionImport Name="GetProductsByRating" EntitySet="Products" ReturnType="Collection(ODataDemo.Product)" m:HttpMethod="GET">
+					<Parameter Name="rating" Type="Edm.Int32" Mode="In"/>
+				</FunctionImport>
+			</EntityContainer>
+		</Schema>
+	</edmx:DataServices>
+</edmx:Edmx>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/resources/metadataWithNavigations.xml
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/resources/metadataWithNavigations.xml b/odata2-lib/odata-client-core/src/test/resources/metadataWithNavigations.xml
new file mode 100644
index 0000000..3adf75d
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/resources/metadataWithNavigations.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<edmx:Edmx Version="1.0" xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx" xmlns:atom="http://www.w3.org/2005/Atom">
+	<edmx:DataServices m:DataServiceVersion="2.0" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
+		<Schema Namespace="ODataSet" xmlns="http://schemas.microsoft.com/ado/2008/09/edm" >
+			<EntityContainer Name="EntityContainer" m:IsDefaultEntityContainer="true">
+				<EntitySet Name="User" EntityType="ODataNS.User" />			
+			</EntityContainer>
+		</Schema>
+		<Schema Namespace="ODataNS" xmlns="http://schemas.microsoft.com/ado/2008/09/edm" >
+			<EntityType Name="User">
+				<Key>
+					<PropertyRef Name="userId"/>
+				</Key>
+						<Property Name="userId" Type="Edm.String" Nullable="false"  MaxLength="100" />
+					</EntityType>
+			
+		</Schema>
+	</edmx:DataServices>
+</edmx:Edmx>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/UriParserImpl.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/UriParserImpl.java b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/UriParserImpl.java
index b7e9c18..47cfa4f 100644
--- a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/UriParserImpl.java
+++ b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/UriParserImpl.java
@@ -112,6 +112,7 @@ public class UriParserImpl extends UriParser {
     return parseAll(pathSegments, convertFromSingleMapToMultiMap(queryParameters));
   }
 
+  
   @Override
   public UriInfo parseAll(final List<PathSegment> pathSegments, final Map<String, List<String>> allQueryParameters)
       throws UriSyntaxException, UriNotMatchingException, EdmException {

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-core/src/main/resources/i18n.properties
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/main/resources/i18n.properties b/odata2-lib/odata-core/src/main/resources/i18n.properties
index 000ad1b..b002b0e 100644
--- a/odata2-lib/odata-core/src/main/resources/i18n.properties
+++ b/odata2-lib/odata-core/src/main/resources/i18n.properties
@@ -66,13 +66,15 @@ org.apache.olingo.odata2.api.edm.EdmLiteralException.NOTEXT=An exception occurre
 org.apache.olingo.odata2.api.edm.EdmLiteralException.LITERALFORMAT=Wrong literal format for literal: '%1$s'.
 org.apache.olingo.odata2.api.edm.EdmLiteralException.UNKNOWNLITERAL=Unknown literal: '%1$s'.
 
+org.apache.olingo.odata2.api.edm.EdmException.TYPEPROBLEM=Type not defined.
+org.apache.olingo.odata2.api.edm.EdmException.ENTITYTYPEPROBLEM=Entity Type not defined.
 org.apache.olingo.odata2.api.edm.EdmException.COMMON=An exception occurred.
 org.apache.olingo.odata2.api.edm.EdmException.PROVIDERPROBLEM=A problem has been detected in the metadata provided by the EDM provider.
 org.apache.olingo.odata2.api.edm.EdmException.PROPERTYNOTFOUND=Invalid property with name '%1$s'
 org.apache.olingo.odata2.api.edm.EdmException.NAVIGATIONPROPERTYNOTFOUND=Invalid navigation property with name '%1$s'
 org.apache.olingo.odata2.api.edm.EdmException.MUSTBENAVIGATIONPROPERTY=The found typed value for '%1$s' must be a navigation property but is not.
 org.apache.olingo.odata2.api.edm.EdmException.MUSTBEPROPERTY=The found typed value for '%1$s' must be a property but is not.
-
+org.apache.olingo.odata2.api.edm.EdmException.ASSOCIATIONNOTFOUND=Association not found.
 org.apache.olingo.odata2.api.edm.EdmSimpleTypeException.COMMON=An exception occurred.
 org.apache.olingo.odata2.api.edm.EdmSimpleTypeException.LITERAL_KIND_MISSING=The literal kind is missing.
 org.apache.olingo.odata2.api.edm.EdmSimpleTypeException.LITERAL_KIND_NOT_SUPPORTED=The literal kind '%1$s' is not supported.
@@ -117,6 +119,9 @@ org.apache.olingo.odata2.api.ep.EntityProviderException.MEDIA_DATA_NOT_INITIAL=R
 org.apache.olingo.odata2.api.ep.EntityProviderException.END_DOCUMENT_EXPECTED=End of document expected but was '%1$s'.
 org.apache.olingo.odata2.api.ep.EntityProviderException.MISSING_RESULTS_ARRAY=Mandatory results array not found.
 org.apache.olingo.odata2.api.ep.EntityProviderException.INVALID_DELETED_ENTRY_METADATA=Invalid delete entry data format (Atom XML Tombstone or Json) 
+org.apache.olingo.odata2.api.ep.EntityProviderException.NULL_VALUE=Entity or expanded entity cannot have null value.
+org.apache.olingo.odata2.api.ep.EntityProviderException.INCORRECT_NAVIGATION_TYPE=Navigation has to be either an Entity or a Map.
+org.apache.olingo.odata2.api.ep.EntityProviderException.MANDATORY_WRITE_PROPERTY=Write properties are mandatory for XML.
 
 ##################################
 # BatchParserexceptions

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-testutil/src/main/java/org/apache/olingo/odata2/testutil/mock/EdmMock.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-testutil/src/main/java/org/apache/olingo/odata2/testutil/mock/EdmMock.java b/odata2-lib/odata-testutil/src/main/java/org/apache/olingo/odata2/testutil/mock/EdmMock.java
index b8cb129..f0e4782 100644
--- a/odata2-lib/odata-testutil/src/main/java/org/apache/olingo/odata2/testutil/mock/EdmMock.java
+++ b/odata2-lib/odata-testutil/src/main/java/org/apache/olingo/odata2/testutil/mock/EdmMock.java
@@ -209,6 +209,22 @@ class EdmMock {
     when(employeeSearchParameter.getType()).thenReturn(EdmSimpleTypeKind.String.getEdmSimpleTypeInstance());
     when(employeeSearchFunctionImport.getParameterNames()).thenReturn(Arrays.asList("q"));
     when(employeeSearchFunctionImport.getParameter("q")).thenReturn(employeeSearchParameter);
+    when(employeeSearchParameter.getName()).thenReturn("q");
+    
+    EdmFunctionImport buildingSearchFunctionImport =
+        createFunctionImportMock(defaultContainer, "BuildingSearch", employeeType, EdmMultiplicity.MANY);
+    when(buildingSearchFunctionImport.getEntitySet()).thenReturn(buildingEntitySet);
+    EdmParameter buildingSearchParameter1 = mock(EdmParameter.class);
+    when(buildingSearchParameter1.getType()).thenReturn(EdmSimpleTypeKind.String.getEdmSimpleTypeInstance());
+    when(buildingSearchFunctionImport.getParameterNames()).thenReturn(Arrays.asList("q", "r"));
+    when(buildingSearchFunctionImport.getParameter("q")).thenReturn(buildingSearchParameter1);
+    when(buildingSearchParameter1.getName()).thenReturn("q");
+    EdmParameter buildingSearchParameter2 = mock(EdmParameter.class);
+    when(buildingSearchParameter2.getType()).thenReturn(EdmSimpleTypeKind.Int16.getEdmSimpleTypeInstance());
+    when(buildingSearchFunctionImport.getParameter("r")).thenReturn(buildingSearchParameter2);
+    when(buildingSearchParameter2.getName()).thenReturn("r");
+    
+    
     createFunctionImportMock(defaultContainer, "AllLocations", locationComplexType, EdmMultiplicity.MANY);
     createFunctionImportMock(defaultContainer, "AllUsedRoomIds", EdmSimpleTypeKind.String.getEdmSimpleTypeInstance(),
         EdmMultiplicity.MANY);
@@ -223,18 +239,20 @@ class EdmMock {
     EdmFacets managerPhotoParameterFacets = mock(EdmFacets.class);
     when(managerPhotoParameterFacets.isNullable()).thenReturn(false);
     when(managerPhotoParameter.getFacets()).thenReturn(managerPhotoParameterFacets);
+    when(managerPhotoParameter.getName()).thenReturn("Id");
     when(managerPhotoFunctionImport.getParameterNames()).thenReturn(Arrays.asList("Id"));
     when(managerPhotoFunctionImport.getParameter("Id")).thenReturn(managerPhotoParameter);
     EdmFunctionImport oldestEmployeeFunctionImport =
         createFunctionImportMock(defaultContainer, "OldestEmployee", employeeType, EdmMultiplicity.ONE);
     when(oldestEmployeeFunctionImport.getEntitySet()).thenReturn(employeeEntitySet);
-
+    
     // Issue with not explicitly nullable parameters and facets
     EdmFunctionImport functionImportNullableParameter =
         createFunctionImportMock(defaultContainer, "FINullableParameter", EdmSimpleTypeKind.Boolean
             .getEdmSimpleTypeInstance(), EdmMultiplicity.ONE);
     EdmParameter nullableFIParameter = mock(EdmParameter.class);
     when(nullableFIParameter.getType()).thenReturn(EdmSimpleTypeKind.String.getEdmSimpleTypeInstance());
+    when(nullableFIParameter.getName()).thenReturn("Id");
     EdmFacets nullableFIParameterFacets = mock(EdmFacets.class);
     when(nullableFIParameterFacets.isNullable()).thenReturn(null);
     when(nullableFIParameterFacets.getMaxLength()).thenReturn(new Integer(1));
@@ -320,6 +338,23 @@ class EdmMock {
     when(edm.getEntityType("RefScenario", "Company")).thenReturn(companyType);
     when(edm.getEntityType("RefScenario", "Organization")).thenReturn(organizationType);
     
+    EdmFunctionImport photoSearchFunctionImport =
+        createFunctionImportMock(photoContainer, "PhotoSearch", photoEntityType,
+            EdmMultiplicity.ONE);
+    when(photoSearchFunctionImport.getEntitySet()).thenReturn(photoEntitySet);
+    EdmParameter photoParameter1 = mock(EdmParameter.class);
+    when(photoParameter1.getType()).thenReturn(EdmSimpleTypeKind.Int16.getEdmSimpleTypeInstance());
+    EdmFacets photoParameterFacets = mock(EdmFacets.class);
+    when(photoParameterFacets.isNullable()).thenReturn(true);
+    when(photoParameter1.getFacets()).thenReturn(photoParameterFacets);
+    when(photoParameter1.getName()).thenReturn("Id");
+    EdmParameter photoParameter2 = mock(EdmParameter.class);
+    when(photoParameter2.getType()).thenReturn(EdmSimpleTypeKind.String.getEdmSimpleTypeInstance());
+    when(photoParameter2.getName()).thenReturn("Type");
+    when(photoSearchFunctionImport.getParameterNames()).thenReturn(Arrays.asList("Id","Type"));
+    when(photoSearchFunctionImport.getParameter("Id")).thenReturn(photoParameter1);
+    when(photoSearchFunctionImport.getParameter("Type")).thenReturn(photoParameter2);
+    
     return edm;
   }
 
@@ -330,7 +365,8 @@ class EdmMock {
 
     EdmNavigationProperty navigationProperty = mock(EdmNavigationProperty.class);
     when(navigationProperty.getName()).thenReturn(name);
-    when(navigationProperty.getType()).thenReturn(navigationType);
+    EdmType type = targetEntitySet.getEntityType();
+    when(navigationProperty.getType()).thenReturn(type);
     when(navigationProperty.getMultiplicity()).thenReturn(multiplicity);
 
     when(entitySet.getEntityType().getProperty(name)).thenReturn(navigationProperty);

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/pom.xml
----------------------------------------------------------------------
diff --git a/odata2-lib/pom.xml b/odata2-lib/pom.xml
index 8e881e6..cc90cdd 100644
--- a/odata2-lib/pom.xml
+++ b/odata2-lib/pom.xml
@@ -29,6 +29,8 @@
         <module>odata-core</module>
         <module>odata-fit</module>
         <module>odata-ref</module>
-        <module>odata-web</module>
+        <module>odata-web</module>        
+		<module>odata-client-api</module>
+		<module>odata-client-core</module>
     </modules>
 </project>


[12/24] olingo-odata2 git commit: [OLINGO-1253]Client Module for Olingo v2

Posted by ar...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/deserializer/XmlErrorDocumentTest.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/deserializer/XmlErrorDocumentTest.java b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/deserializer/XmlErrorDocumentTest.java
new file mode 100644
index 0000000..2a255f1
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/deserializer/XmlErrorDocumentTest.java
@@ -0,0 +1,281 @@
+/*******************************************************************************
+ * 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.client.core.ep.deserializer;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.InputStream;
+import java.util.Locale;
+
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.processor.ODataErrorContext;
+import org.apache.olingo.odata2.client.core.ep.deserializer.XmlErrorDocumentDeserializer;
+import org.apache.olingo.odata2.testutil.helper.StringHelper;
+import org.junit.Test;
+
+/**
+ *
+ */
+public class XmlErrorDocumentTest extends AbstractDeserializerTest {
+
+  private static final String XML_ERROR_DOCUMENT_SIMPLE =
+      "<?xml version='1.0' encoding='UTF-8'?>\n" +
+          "<error xmlns=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\">\n" +
+          "\t<code>ErrorCode</code>\n" +
+          "\t<message xml:lang=\"en-US\">Message</message>\n" +
+          "</error>";
+  private static final String XML_ERROR_DOCUMENT_NULL_LOCALE =
+      "<?xml version='1.0' encoding='UTF-8'?>\n" +
+          "<error xmlns=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\">\n" +
+          "\t<code>ErrorCode</code>\n" +
+          "\t<message xml:lang=\"\">Message</message>\n" +
+          "</error>";
+  private static final String XML_ERROR_DOCUMENT_INNER_ERROR =
+      "<?xml version='1.0' encoding='UTF-8'?>\n" +
+          "<error xmlns=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\">\n" +
+          "\t<code>ErrorCode</code>\n" +
+          "\t<message xml:lang=\"en-US\">Message</message>\n" +
+          "<innererror>Some InnerError</innererror>\n" +
+          "</error>";
+  private static final String XML_ERROR_DOCUMENT_INNER_ERROR_COMPLEX =
+      "<?xml version='1.0' encoding='UTF-8'?>\n" +
+          "<error xmlns=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\">\n" +
+          "\t<code>ErrorCode</code>\n" +
+          "\t<message xml:lang=\"en-US\">Message</message>\n" +
+          "<innererror>" +
+          "<moreInner>More Inner Error</moreInner>" +
+          "</innererror>\n" +
+          "</error>";
+  private static final String XML_ERROR_DOCUMENT_INVALID_XML =
+      "<?xml version='1.0' encoding='UTF-8'?>\n" +
+          "<error xmlns=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\">\n" +
+          "\t<code>ErrorCode</CODE>\n" +
+          "\t<message xml:lang=\"en-US\">Message</message>\n" +
+          "</error>";
+  /* error document with name 'locale' instead of 'lang' for message object */
+  private static final String XML_ERROR_DOCUMENT_UNKNOWN_CONTENT =
+      "<?xml version='1.0' encoding='UTF-8'?>\n" +
+          "<error xmlns=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\">\n" +
+          "\t<code>ErrorCode</code>\n" +
+          "\t<message xml:locale=\"en-US\">Message</message>\n" +
+          "\t<privateMessage>Secret</privateMessage>\n" +
+          "</error>";
+  /* error document without value for message object */
+  private static final String XML_ERROR_DOCUMENT_EMPTY_MESSAGE =
+      "<?xml version='1.0' encoding='UTF-8'?>\n" +
+          "<error xmlns=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\">\n" +
+          "\t<code>ErrorCode</code>\n" +
+          "\t<message xml:lang=\"en-US\" />\n" +
+          "</error>";
+  private static final String XML_ERROR_DOCUMENT_MISSING_MESSAGE =
+      "<?xml version='1.0' encoding='UTF-8'?>\n" +
+          "<error xmlns=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\">\n" +
+          "\t<code>ErrorCode</code>\n" +
+          "</error>";
+  private static final String XML_ERROR_DOCUMENT_MISSING_CODE =
+      "<?xml version='1.0' encoding='UTF-8'?>\n" +
+          "<error xmlns=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\">\n" +
+          "\t<message xml:lang=\"en-US\">Message</message>\n" +
+          "</error>";
+  private static final String XML_ERROR_DOCUMENT_MISSING_ERROR =
+      "<?xml version='1.0' encoding='UTF-8'?>\n" +
+          "<errorForMe xmlns=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\">\n" +
+          "\t<code>ErrorCode</code>\n" +
+          "\t<message xml:lang=\"en-US\">Message</message>\n" +
+          "</errorForMe>";
+  private XmlErrorDocumentDeserializer xedc = new XmlErrorDocumentDeserializer();
+
+  @Test
+  public void simpleErrorDocument() throws Exception {
+    InputStream in = StringHelper.encapsulate(XML_ERROR_DOCUMENT_SIMPLE);
+    ODataErrorContext error = xedc.readError(in);
+
+    assertEquals("Wrong content type", "application/xml", error.getContentType());
+    assertEquals("Wrong message", "Message", error.getMessage());
+    assertEquals("Wrong error code", "ErrorCode", error.getErrorCode());
+    assertEquals("Wrong locale for lang", Locale.US, error.getLocale());
+  }
+
+  @Test
+  public void emptyMessage() throws EntityProviderException {
+    InputStream in = StringHelper.encapsulate(XML_ERROR_DOCUMENT_EMPTY_MESSAGE);
+
+    ODataErrorContext error = xedc.readError(in);
+
+    assertEquals("Wrong content type", "application/xml", error.getContentType());
+    assertEquals("Wrong message", "", error.getMessage());
+    assertEquals("Wrong error code", "ErrorCode", error.getErrorCode());
+    assertEquals("Wrong locale for lang", Locale.US, error.getLocale());
+  }
+
+  @Test
+  public void localeNull() throws Exception {
+    InputStream in = StringHelper.encapsulate(XML_ERROR_DOCUMENT_NULL_LOCALE);
+    ODataErrorContext error = xedc.readError(in);
+
+    assertEquals("Wrong content type", "application/xml", error.getContentType());
+    assertEquals("Wrong message", "Message", error.getMessage());
+    assertEquals("Wrong error code", "ErrorCode", error.getErrorCode());
+    assertNull("Expected NULL for locale", error.getLocale());
+  }
+
+  @Test
+  public void innerError() throws Exception {
+    InputStream in = StringHelper.encapsulate(XML_ERROR_DOCUMENT_INNER_ERROR);
+    ODataErrorContext error = xedc.readError(in);
+
+    assertEquals("Wrong content type", "application/xml", error.getContentType());
+    assertEquals("Wrong message", "Message", error.getMessage());
+    assertEquals("Wrong error code", "ErrorCode", error.getErrorCode());
+    assertEquals("Wrong inner error", "Some InnerError", error.getInnerError());
+  }
+
+  @Test
+  public void innerErrorComplex() throws Exception {
+    InputStream in = StringHelper.encapsulate(XML_ERROR_DOCUMENT_INNER_ERROR_COMPLEX);
+    ODataErrorContext error = xedc.readError(in);
+
+    assertEquals("Wrong content type", "application/xml", error.getContentType());
+    assertEquals("Wrong message", "Message", error.getMessage());
+    assertEquals("Wrong error code", "ErrorCode", error.getErrorCode());
+    assertEquals("Wrong inner error", "<moreInner>More Inner Error</moreInner>", error.getInnerError());
+  }
+
+  @Test
+  public void innerErrorComplexTwo() throws Exception {
+    String innerErrorText = "<firstTag>tagText</firstTag><secondTag>secondText</secondTag>";
+    String innerError = "<innererror>" + innerErrorText + "</innererror>";
+    String errorDocument = XML_ERROR_DOCUMENT_INNER_ERROR_COMPLEX.replaceAll(
+        "<innererror.*error>", innerError);
+    InputStream in = StringHelper.encapsulate(errorDocument);
+    ODataErrorContext error = xedc.readError(in);
+
+    assertEquals("Wrong content type", "application/xml", error.getContentType());
+    assertEquals("Wrong message", "Message", error.getMessage());
+    assertEquals("Wrong error code", "ErrorCode", error.getErrorCode());
+    assertEquals("Wrong inner error", innerErrorText, error.getInnerError());
+  }
+
+  @Test
+  public void innerErrorComplexMoreCharacters() throws Exception {
+    String innerErrorText = "\n\t<firstTag>tagText</firstTag>\n<secondTag>secondText</secondTag>\n";
+    String innerError = "<innererror>" + innerErrorText + "</innererror>";
+    String errorDocument = XML_ERROR_DOCUMENT_INNER_ERROR_COMPLEX.replaceAll(
+        "<innererror.*error>", innerError);
+    InputStream in = StringHelper.encapsulate(errorDocument);
+    ODataErrorContext error = xedc.readError(in);
+
+    assertEquals("Wrong content type", "application/xml", error.getContentType());
+    assertEquals("Wrong message", "Message", error.getMessage());
+    assertEquals("Wrong error code", "ErrorCode", error.getErrorCode());
+    assertEquals("Wrong inner error", innerErrorText, error.getInnerError());
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void invalidJson() throws EntityProviderException {
+    InputStream in = StringHelper.encapsulate(XML_ERROR_DOCUMENT_INVALID_XML);
+    try {
+      xedc.readError(in);
+      fail("Expected exception was not thrown");
+    } catch (EntityProviderException e) {
+      assertEquals(EntityProviderException.INVALID_STATE, e.getMessageReference());
+      throw e;
+    }
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void invalidEmptyDocument() throws EntityProviderException {
+    InputStream in = StringHelper.encapsulate("");
+    try {
+      xedc.readError(in);
+      fail("Expected exception was not thrown");
+    } catch (EntityProviderException e) {
+      assertEquals("Got wrong exception: " + e.getMessageReference().getKey(),
+          EntityProviderException.INVALID_STATE, e.getMessageReference());
+      throw e;
+    }
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void nullParameter() throws EntityProviderException {
+    try {
+      xedc.readError(null);
+      fail("Expected exception was not thrown");
+    } catch (EntityProviderException e) {
+      assertEquals(EntityProviderException.ILLEGAL_ARGUMENT, e.getMessageReference());
+      throw e;
+    }
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void invalidErrorDocumentUnknown() throws EntityProviderException {
+    InputStream in = StringHelper.encapsulate(XML_ERROR_DOCUMENT_UNKNOWN_CONTENT);
+    try {
+      xedc.readError(in);
+      fail("Expected exception was not thrown");
+    } catch (EntityProviderException e) {
+      assertEquals(EntityProviderException.INVALID_CONTENT, e.getMessageReference());
+      throw e;
+    }
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void invalidErrorDocumentMissingError() throws EntityProviderException {
+    InputStream in = StringHelper.encapsulate(XML_ERROR_DOCUMENT_MISSING_ERROR);
+    try {
+      xedc.readError(in);
+      fail("Expected exception was not thrown");
+    } catch (EntityProviderException e) {
+      assertEquals("Got wrong exception: " + e.getMessageReference().getKey(),
+          EntityProviderException.INVALID_STATE, e.getMessageReference());
+      throw e;
+    }
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void invalidErrorDocumentMissingCode() throws EntityProviderException {
+    InputStream in = StringHelper.encapsulate(XML_ERROR_DOCUMENT_MISSING_CODE);
+    try {
+      xedc.readError(in);
+      fail("Expected exception was not thrown");
+    } catch (EntityProviderException e) {
+      assertEquals("Got wrong exception: " + e.getMessageReference().getKey(),
+          EntityProviderException.MISSING_PROPERTY, e.getMessageReference());
+      assertTrue(e.getMessage().contains("code"));
+      throw e;
+    }
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void invalidErrorDocumentMissingMessage() throws EntityProviderException {
+    InputStream in = StringHelper.encapsulate(XML_ERROR_DOCUMENT_MISSING_MESSAGE);
+    try {
+      xedc.readError(in);
+      fail("Expected exception was not thrown");
+    } catch (EntityProviderException e) {
+      assertEquals("Got wrong exception: " + e.getMessageReference().getKey(),
+          EntityProviderException.MISSING_PROPERTY, e.getMessageReference());
+      assertTrue(e.getMessage().contains("message"));
+      throw e;
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/deserializer/XmlFeedDeserializerTest.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/deserializer/XmlFeedDeserializerTest.java b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/deserializer/XmlFeedDeserializerTest.java
new file mode 100644
index 0000000..94dfde4
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/deserializer/XmlFeedDeserializerTest.java
@@ -0,0 +1,241 @@
+/*******************************************************************************
+ * 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.client.core.ep.deserializer;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.List;
+
+import javax.xml.stream.XMLStreamException;
+
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+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.ODataDeltaFeed;
+import org.apache.olingo.odata2.api.ep.feed.ODataFeed;
+import org.apache.olingo.odata2.client.api.edm.ClientEdm;
+import org.apache.olingo.odata2.client.api.edm.EdmDataServices;
+import org.apache.olingo.odata2.client.api.ep.ContentTypeBasedDeserializer;
+import org.apache.olingo.odata2.client.api.ep.DeserializerProperties;
+import org.apache.olingo.odata2.client.api.ep.EntityStream;
+import org.apache.olingo.odata2.client.core.ODataClientImpl;
+import org.apache.olingo.odata2.testutil.mock.MockFacade;
+import org.junit.Test;
+
+import junit.framework.Assert;
+
+public class XmlFeedDeserializerTest extends AbstractXmlDeserializerTest {
+
+  public XmlFeedDeserializerTest(final StreamWriterImplType type) {
+    super(type);
+  }
+
+  
+
+  @Test
+  public void readLargeEmployeesFeed() throws Exception {
+    InputStream file = getFileAsStream("LargeEmployeeFeed.xml");
+    assertNotNull(file);
+    EntityStream es = new EntityStream();
+    es.setContent(file);
+    es.setReadProperties(DEFAULT_PROPERTIES);
+    ODataClientImpl client = new ODataClientImpl();
+    ContentTypeBasedDeserializer deserializer = client.createDeserializer("application/atom+xml");
+    ODataFeed feed =
+        deserializer.readFeed( MockFacade.getMockEdm().getDefaultEntityContainer()
+            .getEntitySet(
+                "Employees"), es);
+    assertNotNull(feed);
+
+    FeedMetadata feedMetadata = feed.getFeedMetadata();
+    assertNotNull(feedMetadata);
+  }
+
+  private InputStream createStreamReader(final String xml) throws
+  XMLStreamException, UnsupportedEncodingException {
+    return new ByteArrayInputStream(xml.getBytes("UTF-8"));
+  }
+  
+  @Test
+  public void readProductsFeedEndToEnd() throws Exception {
+    XmlMetadataDeserializer parser = new XmlMetadataDeserializer();
+    String xml = readFile("metadataProducts.xml");
+    InputStream reader = createStreamReader(xml);
+    EdmDataServices result = parser.readMetadata(reader, true);
+    assertEquals(1, result.getEdm().getSchemas().size());
+    ClientEdm edm = result.getEdm();
+    InputStream file = getFileAsStream("ProductsFeed.xml");
+    assertNotNull(file);
+    EntityStream es = new EntityStream();
+    es.setContent(file);
+    es.setReadProperties(DEFAULT_PROPERTIES);
+    ODataClientImpl client = new ODataClientImpl();
+    ContentTypeBasedDeserializer deserializer = client.createDeserializer("application/atom+xml");
+    ODataFeed feed =
+        deserializer.readFeed( edm.getEntitySets().get(0), es);
+    assertNotNull(feed);
+    
+    List<ODataEntry> oDataEntries = feed.getEntries();
+    
+    for (ODataEntry entry : oDataEntries) {
+      assertEquals(6, entry.getProperties().size());
+      assertEquals(4, ((ODataEntry)entry.getProperties().get("Supplier")).getProperties().size());
+    }
+  }
+
+  /**
+   * Rooms navigate to Employees and has inline entry Teams
+   * E.g: Rooms('1')/nr_Employees?$expand=ne_Team
+   * @throws Exception
+   */
+  @Test
+  public void roomsFeedWithRoomsToEmployeesInlineTeams() throws Exception {
+    InputStream stream = getFileAsStream("RoomsToEmployeesWithInlineTeams.xml");
+    assertNotNull(stream);
+    EntityStream es = new EntityStream();
+    es.setContent(stream);
+    es.setReadProperties(DEFAULT_PROPERTIES);
+    ODataClientImpl client = new ODataClientImpl();
+    ContentTypeBasedDeserializer deserializer = client.createDeserializer("application/atom+xml");
+    ODataFeed feed =
+        deserializer.readFeed( MockFacade.getMockEdm().getDefaultEntityContainer()
+            .getEntitySet(
+                "Employees"), es);
+    assertNotNull(feed);
+    assertEquals(2, feed.getEntries().size());
+
+    for (ODataEntry entry : feed.getEntries()) {
+      assertEquals(10, entry.getProperties().size());
+      assertEquals(3, ((ODataEntry)entry.getProperties().get("ne_Team")).getProperties().size());
+    }
+  }
+ 
+  @Test
+  public void readEmployeesFeedWithInlineCountValid() throws Exception {
+    // prepare
+    String content = readFile("feed_employees_full.xml");
+    assertNotNull(content);
+
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+    InputStream reqContent = createContentAsStream(content);
+
+    // execute
+    XmlEntityDeserializer xec = new XmlEntityDeserializer();
+    DeserializerProperties consumerProperties = DeserializerProperties.init()
+        .build();
+
+    EntityStream es = new EntityStream();
+    es.setContent(reqContent);
+    es.setReadProperties(consumerProperties);
+    
+    ODataFeed feed = xec.readFeed(entitySet, es);
+    assertNotNull(feed);
+
+    FeedMetadata feedMetadata = feed.getFeedMetadata();
+    assertNotNull(feedMetadata);
+
+    int inlineCount = feedMetadata.getInlineCount();
+    // Null means no inlineCount found
+    assertNotNull(inlineCount);
+
+    assertEquals(6, inlineCount);
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void readEmployeesFeedWithInlineCountNegative() throws Exception {
+    // prepare
+    String content = readFile("feed_employees_full.xml").replace("<m:count>6</m:count>", "<m:count>-1</m:count>");
+    assertNotNull(content);
+
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+    InputStream reqContent = createContentAsStream(content);
+
+    // execute
+    XmlEntityDeserializer xec = new XmlEntityDeserializer();
+    DeserializerProperties consumerProperties = DeserializerProperties.init()
+        .build();
+
+    EntityStream es = new EntityStream();
+    es.setContent(reqContent);
+    es.setReadProperties(consumerProperties);
+    try {
+      xec.readFeed(entitySet,  es);
+    } catch (EntityProviderException e) {
+      assertEquals(EntityProviderException.INLINECOUNT_INVALID, e.getMessageReference());
+      throw e;
+    }
+
+    Assert.fail("Exception expected");
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void readEmployeesFeedWithInlineCountLetters() throws Exception {
+    // prepare
+    String content = readFile("feed_employees_full.xml").replace("<m:count>6</m:count>", "<m:count>AAA</m:count>");
+    assertNotNull(content);
+
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+    InputStream reqContent = createContentAsStream(content);
+
+    // execute
+    XmlEntityDeserializer xec = new XmlEntityDeserializer();
+    DeserializerProperties consumerProperties = DeserializerProperties.init()
+        .build();
+
+    EntityStream es = new EntityStream();
+    es.setContent(reqContent);
+    es.setReadProperties(consumerProperties);
+    try {
+      xec.readFeed(entitySet, es);
+    } catch (EntityProviderException e) {
+      assertEquals(EntityProviderException.INLINECOUNT_INVALID, e.getMessageReference());
+      throw e;
+    }
+
+    Assert.fail("Exception expected");
+  }
+  @Test
+  public void readDeltaFeed() throws Exception {
+    // prepare
+    String content = readFile("feed_with_deleted_entries.xml");
+    assertNotNull(content);
+
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+    InputStream reqContent = createContentAsStream(content);
+    EntityStream stream = new EntityStream();
+    XmlEntityDeserializer xec = new XmlEntityDeserializer();
+    DeserializerProperties consumerProperties = DeserializerProperties.init().build();
+    stream.setContent(reqContent);
+    stream.setReadProperties(consumerProperties);
+    ODataDeltaFeed deltaFeed = xec.readFeed(entitySet, stream);
+
+    assertNotNull(deltaFeed);
+
+    assertNotNull(deltaFeed.getDeletedEntries());
+    assertNotNull(deltaFeed.getEntries());
+
+    assertEquals(1, deltaFeed.getEntries().size());
+    assertEquals(1, deltaFeed.getDeletedEntries().size());
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/deserializer/XmlMetadataAssociationTest.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/deserializer/XmlMetadataAssociationTest.java b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/deserializer/XmlMetadataAssociationTest.java
new file mode 100644
index 0000000..84a843f
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/deserializer/XmlMetadataAssociationTest.java
@@ -0,0 +1,504 @@
+package org.apache.olingo.odata2.client.core.ep.deserializer;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.stream.XMLStreamException;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmAnnotationAttribute;
+import org.apache.olingo.odata2.api.edm.EdmAssociation;
+import org.apache.olingo.odata2.api.edm.EdmAssociationEnd;
+import org.apache.olingo.odata2.api.edm.EdmAssociationSet;
+import org.apache.olingo.odata2.api.edm.EdmAssociationSetEnd;
+import org.apache.olingo.odata2.api.edm.EdmEntityContainer;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmEntityType;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
+import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.client.api.edm.EdmDataServices;
+import org.apache.olingo.odata2.client.api.edm.EdmSchema;
+import org.junit.Test;
+
+public class XmlMetadataAssociationTest {
+  private static final String NAMESPACE = "RefScenario";
+  private static final String NAMESPACE2 = "RefScenario2";
+  private static final String ASSOCIATION = "ManagerEmployees";
+  
+  private final String[] propertyNames = { "EmployeeId", "EmployeeName", "Location" };
+  
+  private final String xmlWithAssociation =
+      "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\""
+          + Edm.NAMESPACE_EDMX_2007_06
+          + "\">"
+          + "<edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\""
+          + Edm.NAMESPACE_M_2007_08
+          + "\">"
+          + "<Schema Namespace=\""
+          + NAMESPACE
+          + "\" xmlns=\""
+          + Edm.NAMESPACE_EDM_2008_09
+          + "\">"
+          + "<EntityType Name= \"Employee\">"
+          + "<Key><PropertyRef Name=\"EmployeeId\"/></Key>"
+          + "<Property Name=\""
+          + propertyNames[0]
+          + "\" Type=\"Edm.String\" Nullable=\"false\"/>"
+          + "<NavigationProperty Name=\"ne_Manager\" Relationship=\"RefScenario.ManagerEmployees\" " +
+          "FromRole=\"r_Employees\" ToRole=\"r_Manager\" />"
+          + "</EntityType>"
+          + "<EntityType Name=\"Manager\" BaseType=\"RefScenario.Employee\" m:HasStream=\"true\">"
+          + "<NavigationProperty Name=\"nm_Employees\" Relationship=\"RefScenario.ManagerEmployees\" " +
+          "FromRole=\"r_Manager\" ToRole=\"r_Employees\" />"
+          + "</EntityType>" + "<Association Name=\"" + ASSOCIATION + "\">"
+          + "<End Type=\"RefScenario.Employee\" Multiplicity=\"*\" Role=\"r_Employees\">"
+          + "<OnDelete Action=\"Cascade\"/>" + "</End>"
+          + "<End Type=\"RefScenario.Manager\" Multiplicity=\"1\" Role=\"r_Manager\"/>" + "</Association>"
+          + "</Schema>" + "<Schema Namespace=\"" + NAMESPACE2 + "\" xmlns=\"" + Edm.NAMESPACE_EDM_2008_09 + "\">"
+          + "<EntityContainer Name=\"Container1\" m:IsDefaultEntityContainer=\"true\">"
+          + "<EntitySet Name=\"Employees\" EntityType=\"RefScenario.Employee\"/>"
+          + "<EntitySet Name=\"Managers\" EntityType=\"RefScenario.Manager\"/>" + "<AssociationSet Name=\""
+          + ASSOCIATION + "\" Association=\"RefScenario." + ASSOCIATION + "\">"
+          + "<End EntitySet=\"Managers\" Role=\"r_Manager\"/>" + "<End EntitySet=\"Employees\" Role=\"r_Employees\"/>"
+          + "</AssociationSet>" + "</EntityContainer>" + "</Schema>" + "</edmx:DataServices>" + "</edmx:Edmx>";
+  private final String xmlWithAssociationWithRC =
+      "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\""
+          + Edm.NAMESPACE_EDMX_2007_06
+          + "\">"
+          + "<edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\""
+          + Edm.NAMESPACE_M_2007_08
+          + "\">"
+          + "<Schema Namespace=\""
+          + NAMESPACE
+          + "\" xmlns=\""
+          + Edm.NAMESPACE_EDM_2008_09
+          + "\">"
+          + "<EntityType Name= \"Employee\">"
+          + "<Key><PropertyRef Name=\"EmployeeId\"/></Key>"
+          + "<Property Name=\""
+          + propertyNames[0]
+          + "\" Type=\"Edm.String\" Nullable=\"false\"/>"
+          + "<NavigationProperty Name=\"ne_Manager\" Relationship=\"RefScenario.ManagerEmployees\" " +
+          "FromRole=\"r_Employees\" ToRole=\"r_Manager\" />"
+          + "</EntityType>"
+          + "<EntityType Name=\"Manager\" BaseType=\"RefScenario.Employee\" m:HasStream=\"true\">"
+          + "<NavigationProperty Name=\"nm_Employees\" Relationship=\"RefScenario.ManagerEmployees\" " +
+          "FromRole=\"r_Manager\" ToRole=\"r_Employees\" />"
+          + "</EntityType>" + "<Association Name=\"" + ASSOCIATION + "\">"
+          + "<End Type=\"RefScenario.Employee\" Multiplicity=\"*\" Role=\"r_Employees\">"
+          + "<OnDelete Action=\"Cascade\"/>" + "</End>"
+          + "<End Type=\"RefScenario.Manager\" Multiplicity=\"1\" Role=\"r_Manager\"/>"
+          + "<ReferentialConstraint><Principal Role=\"r_Employees\">"
+          + "<PropertyRef Name=\"EmployeeId\"/></Principal><Dependent Role=\"r_Manager\">"
+          + "<PropertyRef Name=\"EmployeeId\"/></Dependent></ReferentialConstraint>"          
+          + "</Association>"
+          + "</Schema>" + "<Schema Namespace=\"" + NAMESPACE2 + "\" xmlns=\"" + Edm.NAMESPACE_EDM_2008_09 + "\">"
+          + "<EntityContainer Name=\"Container1\" m:IsDefaultEntityContainer=\"true\">"
+          + "<EntitySet Name=\"Employees\" EntityType=\"RefScenario.Employee\"/>"
+          + "<EntitySet Name=\"Managers\" EntityType=\"RefScenario.Manager\"/>" + "<AssociationSet Name=\""
+          + ASSOCIATION + "\" Association=\"RefScenario." + ASSOCIATION + "\">"
+          + "<End EntitySet=\"Managers\" Role=\"r_Manager\"/>" + "<End EntitySet=\"Employees\" Role=\"r_Employees\"/>"
+          + "</AssociationSet>" + "</EntityContainer>" + "</Schema>" + "</edmx:DataServices>" + "</edmx:Edmx>";
+
+    @Test
+  public void testAssociationSet() throws XMLStreamException, EntityProviderException,
+  EdmException, UnsupportedEncodingException {
+    XmlMetadataDeserializer parser = new XmlMetadataDeserializer();
+    InputStream content = createStreamReader(xmlWithAssociation);
+    EdmDataServices result = parser.readMetadata(content, true);
+    for (EdmSchema schema : result.getEdm().getSchemas()) {
+      for (EdmEntityContainer container : schema.getEntityContainers()) {
+        assertEquals(NAMESPACE2, schema.getNamespace());
+        assertEquals("Container1", container.getName());
+        assertEquals(Boolean.TRUE, container.isDefaultEntityContainer());
+        for (EdmAssociationSet assocSet : container.getAssociationSets()) {
+          assertNotNull(assocSet.getEntityContainer());
+          assertEquals(ASSOCIATION, assocSet.getName());
+          assertEquals(ASSOCIATION, assocSet.getAssociation().getName());
+          assertEquals(NAMESPACE, assocSet.getAssociation().getNamespace());
+          EdmAssociationSetEnd end;
+          if ("Employees".equals(assocSet.getEnd("r_Employees").getEntitySet().getName())) {
+            end = assocSet.getEnd("r_Employees");
+          } else {
+            end = assocSet.getEnd("r_Manager");
+          }
+          assertEquals("r_Employees", end.getRole());
+          assertEquals("Employees", end.getEntitySet().getName());
+        }
+      }
+    }
+  }
+    
+    @Test
+    public void testAssociationSetWithRC() throws XMLStreamException, EntityProviderException,
+    EdmException, UnsupportedEncodingException {
+      XmlMetadataDeserializer parser = new XmlMetadataDeserializer();
+      InputStream content = createStreamReader(xmlWithAssociationWithRC);
+      EdmDataServices result = parser.readMetadata(content, true);
+      EdmAssociation associations = (EdmAssociation) result.getEdm().getSchemas().get(0).getAssociations().get(0);
+      assertEquals(1, associations.getReferentialConstraint().getPrincipal().getPropertyRefNames().size());
+      assertEquals(1, associations.getReferentialConstraint().getDependent().getPropertyRefNames().size());
+      assertEquals("EmployeeId", associations.getReferentialConstraint().getPrincipal().getPropertyRefNames().get(0));
+      assertEquals("EmployeeId", associations.getReferentialConstraint().getDependent().getPropertyRefNames().get(0));
+      
+    }
+    
+    @Test
+    public void testRelatedEntitySet() throws XMLStreamException, EntityProviderException,
+    EdmException, UnsupportedEncodingException {
+      XmlMetadataDeserializer parser = new XmlMetadataDeserializer();
+      InputStream content = createStreamReader(xmlWithAssociation);
+      EdmDataServices result = parser.readMetadata(content, true);
+      for (EdmSchema schema : result.getEdm().getSchemas()) {
+        for (EdmEntityContainer container : schema.getEntityContainers()) {
+          assertEquals(NAMESPACE2, schema.getNamespace());
+          assertEquals("Container1", container.getName());
+          assertEquals(Boolean.TRUE, container.isDefaultEntityContainer());
+          for (EdmEntitySet entitySet : container.getEntitySets()) {
+            assertNotNull(entitySet.getEntityContainer());
+            for (EdmEntityType entityType : result.getEdm().getSchemas().get(0).getEntityTypes()) {
+              for (String navigationPropertyName : entityType.getNavigationPropertyNames()) {
+                EdmNavigationProperty navigationProperty = (EdmNavigationProperty) entityType
+                    .getProperty(navigationPropertyName);
+                if(entitySet.getName().equals("Managers") && navigationProperty.getName().equals("nm_Employees")){
+                  assertNotNull(entitySet.getRelatedEntitySet(navigationProperty));
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+    
+  @Test
+  public void testAssociation() throws XMLStreamException, EntityProviderException,
+  EdmException, UnsupportedEncodingException {
+    XmlMetadataDeserializer parser = new XmlMetadataDeserializer();
+    InputStream reader = createStreamReader(xmlWithAssociation);
+    EdmDataServices result = parser.readMetadata(reader, true);
+    assertEquals("2.0", result.getDataServiceVersion());
+    for (EdmSchema schema : result.getEdm().getSchemas()) {
+      for (EdmAssociation association : schema.getAssociations()) {
+        EdmAssociationEnd end;
+        assertEquals(ASSOCIATION, association.getName());
+        if ("Employee".equals(association.getEnd1().getEntityType().getName())) {
+          end = association.getEnd1();
+        } else {
+          end = association.getEnd2();
+        }
+        assertEquals(EdmMultiplicity.MANY, end.getMultiplicity());
+        assertEquals("r_Employees", end.getRole());
+      }
+    }
+  }
+  
+  private InputStream createStreamReader(final String xml) throws XMLStreamException,
+  UnsupportedEncodingException {
+    return new ByteArrayInputStream(xml.getBytes("UTF-8"));
+  }
+  @Test(expected = EntityProviderException.class)
+  public void testMissingTypeAtAssociation() throws Exception {
+    final String xmlWithInvalidAssociation =
+        "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\""
+            + Edm.NAMESPACE_EDMX_2007_06
+            + "\">"
+            + "<edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\""
+            + Edm.NAMESPACE_M_2007_08
+            + "\">"
+            + "<Schema Namespace=\""
+            + NAMESPACE
+            + "\" xmlns=\""
+            + Edm.NAMESPACE_EDM_2008_09
+            + "\">"
+            + "<EntityType Name= \"Employee\">"
+            + "<Key><PropertyRef Name=\"EmployeeId\"/></Key>"
+            + "<Property Name=\""
+            + propertyNames[0]
+            + "\" Type=\"Edm.String\" Nullable=\"false\"/>"
+            + "<NavigationProperty Name=\"ne_Manager\" Relationship=\"RefScenario.ManagerEmployees\" " +
+            "FromRole=\"r_Employees\" ToRole=\"r_Manager\" />"
+            + "</EntityType>" + "<EntityType Name=\"Manager\" BaseType=\"RefScenario.Employee\" m:HasStream=\"true\">"
+            + "</EntityType>" + "<Association Name=\"ManagerEmployees\">"
+            + "<End Multiplicity=\"*\" Role=\"r_Employees\"/>"
+            + "<End Type=\"RefScenario.Manager\" Multiplicity=\"1\" Role=\"r_Manager\"/>"
+            + "</Association></Schema></edmx:DataServices></edmx:Edmx>";
+    XmlMetadataDeserializer parser = new XmlMetadataDeserializer();
+    InputStream reader = createStreamReader(xmlWithInvalidAssociation);
+    try {
+      parser.readMetadata(reader, true);
+    } catch (EntityProviderException e) {
+      assertEquals(EntityProviderException.MISSING_ATTRIBUTE.getKey(), e.getMessageReference().getKey());
+      assertEquals(2, e.getMessageReference().getContent().size());
+      assertEquals("Type", e.getMessageReference().getContent().get(0));
+      assertEquals("End", e.getMessageReference().getContent().get(1));
+      throw e;
+    }
+  }
+  
+  @Test(expected = EntityProviderException.class)
+  public void testMissingAssociation() throws Exception {
+    final String xmlWithAssociation =
+        "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\""
+            + Edm.NAMESPACE_EDMX_2007_06
+            + "\">"
+            + "<edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\""
+            + Edm.NAMESPACE_M_2007_08
+            + "\">"
+            + "<Schema Namespace=\""
+            + NAMESPACE
+            + "\" xmlns=\""
+            + Edm.NAMESPACE_EDM_2008_09
+            + "\">"
+            + "<EntityType Name= \"Employee\">"
+            + "<Key><PropertyRef Name=\"EmployeeId\"/></Key>"
+            + "<Property Name=\""
+            + propertyNames[0]
+            + "\" Type=\"Edm.String\" Nullable=\"false\"/>"
+            + "<NavigationProperty Name=\"ne_Manager\" Relationship=\"RefScenario.ManagerEmployees\" " +
+            "FromRole=\"r_Employees\" ToRole=\"r_Manager\" />"
+            + "</EntityType>" + "<EntityContainer Name=\"Container1\" m:IsDefaultEntityContainer=\"true\">"
+            + "<EntitySet Name=\"Employees\" EntityType=\"RefScenario.Employee\"/>" + "<AssociationSet Name=\""
+            + ASSOCIATION
+            // + "\" Association=\"RefScenario." + ASSOCIATION
+            + "\">" + "<End EntitySet=\"Employees\" Role=\"r_Employees\"/>" + "</AssociationSet>"
+            + "</EntityContainer>" + "</Schema>" + "</edmx:DataServices></edmx:Edmx>";
+    XmlMetadataDeserializer parser = new XmlMetadataDeserializer();
+    InputStream reader = createStreamReader(xmlWithAssociation);
+    try {
+      parser.readMetadata(reader, true);
+    } catch (EntityProviderException e) {
+      assertEquals(EntityProviderException.MISSING_ATTRIBUTE.getKey(), e.getMessageReference().getKey());
+      assertEquals(2, e.getMessageReference().getContent().size());
+      assertEquals("Association", e.getMessageReference().getContent().get(0));
+      assertEquals("AssociationSet", e.getMessageReference().getContent().get(1));
+      throw e;
+    }
+  }
+  
+  @Test(expected = EdmException.class)
+  public void testInvalidAssociation() throws XMLStreamException, 
+  EntityProviderException, EdmException, UnsupportedEncodingException {
+    final String xmlWithInvalidAssociationSet =
+        "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\""
+            + Edm.NAMESPACE_EDMX_2007_06
+            + "\">"
+            + "<edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\""
+            + Edm.NAMESPACE_M_2007_08
+            + "\">"
+            + "<Schema Namespace=\""
+            + NAMESPACE
+            + "\" xmlns=\""
+            + Edm.NAMESPACE_EDM_2008_09
+            + "\">"
+            + "<EntityType Name= \"Employee\">"
+            + "<Key><PropertyRef Name=\"EmployeeId\"/></Key>"
+            + "<Property Name=\""
+            + propertyNames[0]
+            + "\" Type=\"Edm.String\" Nullable=\"false\"/>"
+            + "<NavigationProperty Name=\"ne_Manager\" Relationship=\"RefScenario.ManagerEmployees\" " +
+            "FromRole=\"r_Employees\" ToRole=\"r_Manager\" />"
+            + "</EntityType>"
+            + "<EntityType Name=\"Manager\" BaseType=\"RefScenario.Employee\" m:HasStream=\"true\">"
+            + "<NavigationProperty Name=\"nm_Employees\" Relationship=\"RefScenario.ManagerEmployees\" " +
+            "FromRole=\"r_Manager\" ToRole=\"r_Employees\" />"
+            + "</EntityType>" + "<Association Name=\"" + ASSOCIATION + "\">"
+            + "<End Type=\"RefScenario.Employee\" Multiplicity=\"*\" Role=\"r_Employees\">"
+            + "<OnDelete Action=\"Cascade\"/>" + "</End>"
+            + "<End Type=\"RefScenario.Manager\" Multiplicity=\"1\" Role=\"r_Manager\"/>" + "</Association>"
+            + "<EntityContainer Name=\"Container1\" m:IsDefaultEntityContainer=\"true\">"
+            + "<EntitySet Name=\"Employees\" EntityType=\"RefScenario.Employee\"/>"
+            + "<EntitySet Name=\"Managers\" EntityType=\"RefScenario.Manager\"/>" + "<AssociationSet Name=\""
+            + ASSOCIATION + "\" Association=\"RefScenario2." + ASSOCIATION + "\">"
+            + "<End EntitySet=\"Managers\" Role=\"r_Manager\"/>"
+            + "<End EntitySet=\"Employees\" Role=\"r_Employees\"/>" + "</AssociationSet>" + "</EntityContainer>"
+            + "</Schema>" + "</edmx:DataServices>" + "</edmx:Edmx>";
+    XmlMetadataDeserializer parser = new XmlMetadataDeserializer();
+    InputStream reader = createStreamReader(xmlWithInvalidAssociationSet);
+    parser.readMetadata(reader, true);
+
+  }
+  @Test(expected = EdmException.class)
+  public void testInvalidAssociationEnd() throws XMLStreamException,
+  EntityProviderException, EdmException, UnsupportedEncodingException {
+    final String employees = "r_Employees";
+    final String manager = "r_Manager";
+    final String xmlWithInvalidAssociationSetEnd =
+        "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\"" + Edm.NAMESPACE_EDMX_2007_06 + "\">"
+            + "<edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\"" + Edm.NAMESPACE_M_2007_08 + "\">"
+            + "<Schema Namespace=\"" + NAMESPACE + "\" xmlns=\"" + Edm.NAMESPACE_EDM_2008_09 + "\">"
+            + "<EntityType Name= \"Employee\">" + "<Key><PropertyRef Name=\"EmployeeId\"/></Key>" + "<Property Name=\""
+            + propertyNames[0] + "\" Type=\"Edm.String\" Nullable=\"false\"/>"
+            + "<NavigationProperty Name=\"ne_Manager\" Relationship=\"RefScenario.ManagerEmployees\" FromRole=\""
+            + employees + "\" ToRole=\"" + manager + "\" />" + "</EntityType>"
+            + "<EntityType Name=\"Manager\" BaseType=\"RefScenario.Employee\" m:HasStream=\"true\">"
+            + "<NavigationProperty Name=\"nm_Employees\" Relationship=\"RefScenario.ManagerEmployees\" FromRole=\""
+            + manager + "\" ToRole=\"" + employees + "\" />" + "</EntityType>" + "<Association Name=\"" + ASSOCIATION
+            + "\">"
+            + "<End Type=\"RefScenario.Employee\" Multiplicity=\"*\" Role=\"" + employees + "1" + "\"/>"
+            + "<End Type=\"RefScenario.Manager\" Multiplicity=\"1\" Role=\"" + manager + "\"/>" + "</Association>"
+            + "<EntityContainer Name=\"Container1\" m:IsDefaultEntityContainer=\"true\">"
+            + "<EntitySet Name=\"Employees\" EntityType=\"RefScenario.Employee\"/>"
+            + "<EntitySet Name=\"Managers\" EntityType=\"RefScenario.Manager\"/>" + "<AssociationSet Name=\""
+            + ASSOCIATION + "\" Association=\"RefScenario2." + ASSOCIATION + "\">"
+            + "<End EntitySet=\"Managers\" Role=\"" + manager + "\"/>" + "<End EntitySet=\"Employees\" Role=\""
+            + employees + "\"/>" + "</AssociationSet>" + "</EntityContainer>" + "</Schema>" + "</edmx:DataServices>"
+            + "</edmx:Edmx>";
+    XmlMetadataDeserializer parser = new XmlMetadataDeserializer();
+    InputStream reader = createStreamReader(xmlWithInvalidAssociationSetEnd);
+    parser.readMetadata(reader, true);
+
+  }
+  
+  @Test(expected = EdmException.class)
+  public void testInvalidAssociationEnd2() throws XMLStreamException, 
+  EntityProviderException, EdmException, UnsupportedEncodingException {
+    final String employees = "r_Employees";
+    final String manager = "r_Manager";
+    final String xmlWithInvalidAssociationSetEnd =
+        "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\"" + Edm.NAMESPACE_EDMX_2007_06 + "\">"
+            + "<edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\"" + Edm.NAMESPACE_M_2007_08 + "\">"
+            + "<Schema Namespace=\"" + NAMESPACE + "\" xmlns=\"" + Edm.NAMESPACE_EDM_2008_09 + "\">"
+            + "<EntityType Name= \"Employee\">" + "<Key><PropertyRef Name=\"EmployeeId\"/></Key>" + "<Property Name=\""
+            + propertyNames[0] + "\" Type=\"Edm.String\" Nullable=\"false\"/>"
+            + "<NavigationProperty Name=\"ne_Manager\" Relationship=\"RefScenario.ManagerEmployees\" FromRole=\""
+            + employees + "\" ToRole=\"" + manager + "\" />" + "</EntityType>"
+            + "<EntityType Name=\"Manager\" BaseType=\"RefScenario.Employee\" m:HasStream=\"true\">"
+            + "<NavigationProperty Name=\"nm_Employees\" Relationship=\"RefScenario.ManagerEmployees\" FromRole=\""
+            + manager + "\" ToRole=\"" + employees + "\" />" + "</EntityType>" + "<Association Name=\"" + ASSOCIATION
+            + "\">"
+            + "<End Type=\"RefScenario.Employee\" Multiplicity=\"*\" Role=\"" + employees + "\"/>"
+            + "<End Type=\"RefScenario.Manager\" Multiplicity=\"1\" Role=\"" + manager + "\"/>" + "</Association>"
+            + "<EntityContainer Name=\"Container1\" m:IsDefaultEntityContainer=\"true\">"
+            + "<EntitySet Name=\"Employees\" EntityType=\"RefScenario.Employee\"/>"
+            + "<EntitySet Name=\"Managers\" EntityType=\"RefScenario.Manager\"/>" + "<AssociationSet Name=\""
+            + ASSOCIATION + "\" Association=\"RefScenario2." + ASSOCIATION + "\">"
+            + "<End EntitySet=\"Managers\" Role=\"" + manager + "\"/>" + "<End EntitySet=\"Managers\" Role=\""
+            + manager + "\"/>" + "</AssociationSet>" + "</EntityContainer>" + "</Schema>" + "</edmx:DataServices>"
+            + "</edmx:Edmx>";
+    XmlMetadataDeserializer parser = new XmlMetadataDeserializer();
+    InputStream reader = createStreamReader(xmlWithInvalidAssociationSetEnd);
+    parser.readMetadata(reader, true);
+
+  }
+  
+  @Test
+  public void testAnnoationsOnAssociationSet() throws Exception {
+    final String employees = "r_Employees";
+    final String manager = "r_Manager";
+    final String xmlWithInvalidAssociationSetEnd =
+        "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\"" + Edm.NAMESPACE_EDMX_2007_06 + "\" "
+            + "xmlns:sap=\"http://www.sap.com/Protocols/SAPData\">"
+            + "<edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\"" + Edm.NAMESPACE_M_2007_08 + "\">"
+            + "<Schema Namespace=\"" + NAMESPACE + "\" xmlns=\"" + Edm.NAMESPACE_EDM_2008_09 + "\">"
+            + "<EntityType Name= \"Employee\">" + "<Key><PropertyRef Name=\"EmployeeId\"/></Key>" + "<Property Name=\""
+            + propertyNames[0] + "\" Type=\"Edm.String\" Nullable=\"false\"/>"
+            + "<NavigationProperty Name=\"ne_Manager\" Relationship=\"RefScenario.ManagerEmployees\" FromRole=\""
+            + employees + "\" ToRole=\"" + manager + "\" />" + "</EntityType>"
+            + "<EntityType Name=\"Manager\" BaseType=\"RefScenario.Employee\" m:HasStream=\"true\">"
+            + "<NavigationProperty Name=\"nm_Employees\" Relationship=\"RefScenario.ManagerEmployees\" FromRole=\""
+            + manager + "\" ToRole=\"" + employees + "\" />" + "</EntityType>" + "<Association Name=\"" + ASSOCIATION
+            + "\">"
+            + "<End Type=\"RefScenario.Employee\" Multiplicity=\"*\" Role=\"" + employees + "\"/>"
+            + "<End Type=\"RefScenario.Manager\" Multiplicity=\"1\" Role=\"" + manager + "\"/>" + "</Association>"
+            + "<EntityContainer Name=\"Container1\" m:IsDefaultEntityContainer=\"true\">"
+            + "<EntitySet Name=\"Employees\" EntityType=\"RefScenario.Employee\"/>"
+            + "<EntitySet Name=\"Managers\" EntityType=\"RefScenario.Manager\"/>" + "<AssociationSet Name=\""
+            + ASSOCIATION + "\" Association=\"RefScenario." + ASSOCIATION + "\" "
+            + "sap:creatable=\"true\" sap:updatable=\"true\" "
+            + "sap:deletable=\"false\">"
+            + "<End EntitySet=\"Managers\" Role=\"" + manager + "\"/>" + "<End EntitySet=\"Employees\" Role=\""
+            + employees + "\"/>" + "</AssociationSet>" + "</EntityContainer>" + "</Schema>" + "</edmx:DataServices>"
+            + "</edmx:Edmx>";
+    XmlMetadataDeserializer parser = new XmlMetadataDeserializer();
+    InputStream reader = createStreamReader(xmlWithInvalidAssociationSetEnd);
+    EdmDataServices result = parser.readMetadata(reader, true);
+    List<String> annotationList = new ArrayList<String>();
+    annotationList.add("creatable");
+    annotationList.add("updatable");
+    annotationList.add("deletable");
+    for (EdmSchema schema : result.getEdm().getSchemas()) {
+      for (EdmEntityContainer container : schema.getEntityContainers()) {
+        for (EdmAssociationSet associationSet : container.getAssociationSets()) {
+          assertEquals("ManagerEmployees", associationSet.getName());
+          int i = 0;
+          for (EdmAnnotationAttribute annotationAttr : associationSet.getAnnotations().getAnnotationAttributes()) {
+            assertEquals(annotationList.get(i), annotationAttr.getName());
+            assertEquals("sap", annotationAttr.getPrefix());
+            assertEquals("http://www.sap.com/Protocols/SAPData", annotationAttr.getNamespace());
+            i++;
+          }
+        }
+      }
+    }
+    
+  }
+  
+  @Test
+  public void testRelatedEntitySetWithCyclicAssociation() throws Exception {
+    final String employees = "r_Employees";
+    final String manager = "r_Manager";
+    final String xmlWithInvalidAssociationSetEnd =
+        "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\"" + Edm.NAMESPACE_EDMX_2007_06 + "\" "
+            + "xmlns:sap=\"http://www.sap.com/Protocols/SAPData\">"
+            + "<edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\"" + Edm.NAMESPACE_M_2007_08 + "\">"
+            + "<Schema Namespace=\"" + NAMESPACE + "\" xmlns=\"" + Edm.NAMESPACE_EDM_2008_09 + "\">"
+            + "<EntityType Name= \"Employee\">" + "<Key><PropertyRef Name=\"EmployeeId\"/></Key>" + "<Property Name=\""
+            + propertyNames[0] + "\" Type=\"Edm.String\" Nullable=\"false\"/>"
+            + "<NavigationProperty Name=\"ne_Manager\" Relationship=\"RefScenario.ManagerEmployees\" FromRole=\""
+            + employees + "\" ToRole=\"" + manager + "\" />" + "</EntityType>"
+            + "<EntityType Name=\"Manager\" BaseType=\"RefScenario.Employee\" m:HasStream=\"true\">"
+            + "<NavigationProperty Name=\"nm_Employees\" Relationship=\"RefScenario.ManagerEmployees\" FromRole=\""
+            + manager + "\" ToRole=\"" + employees + "\" />" + "</EntityType>" + "<Association Name=\"" + ASSOCIATION
+            + "\">"
+            + "<End Type=\"RefScenario.Employee\" Multiplicity=\"*\" Role=\"" + employees + "\"/>"
+            + "<End Type=\"RefScenario.Manager\" Multiplicity=\"1\" Role=\"" + manager + "\"/>" + "</Association>"
+            + "<EntityContainer Name=\"Container1\" m:IsDefaultEntityContainer=\"true\">"
+            + "<EntitySet Name=\"Employees\" EntityType=\"RefScenario.Employee\"/>"
+            + "<EntitySet Name=\"Managers\" EntityType=\"RefScenario.Manager\"/>" + "<AssociationSet Name=\""
+            + ASSOCIATION + "\" Association=\"RefScenario." + ASSOCIATION + "\" "
+            + "sap:creatable=\"true\" sap:updatable=\"true\" "
+            + "sap:deletable=\"false\">"
+            + "<End EntitySet=\"Managers\" Role=\"" + manager + "\"/>" + "<End EntitySet=\"Employees\" Role=\""
+            + employees + "\"/>" + "</AssociationSet>" + "</EntityContainer>" + "</Schema>" + "</edmx:DataServices>"
+            + "</edmx:Edmx>";
+    XmlMetadataDeserializer parser = new XmlMetadataDeserializer();
+    InputStream reader = createStreamReader(xmlWithInvalidAssociationSetEnd);
+    EdmDataServices result = parser.readMetadata(reader, true);
+    List<String> annotationList = new ArrayList<String>();
+    annotationList.add("creatable");
+    annotationList.add("updatable");
+    annotationList.add("deletable");
+    for (EdmSchema schema : result.getEdm().getSchemas()) {
+      for (EdmEntityContainer container : schema.getEntityContainers()) {
+        for (EdmEntitySet entitySet : container.getEntitySets()) {
+          for(EdmEntityType entityType:schema.getEntityTypes()){
+            List<String> navigationPropertyNames = entityType.getNavigationPropertyNames();
+            for (String navigationPropertyName : navigationPropertyNames) {
+              EdmNavigationProperty navigationProperty = (EdmNavigationProperty) entityType
+                  .getProperty(navigationPropertyName);
+              if((entitySet.getName().equals("Managers") && navigationProperty.getName().equals("nm_Employees")) || 
+                  entitySet.getName().equals("Employees") && navigationProperty.getName().equals("ne_Manager") ){
+                assertNotNull(entitySet.getRelatedEntitySet(navigationProperty));
+              }else{
+                assertNull(entitySet.getRelatedEntitySet(navigationProperty));
+              }
+            }
+          }
+        }
+      }
+    }
+    
+  }
+  
+
+  
+}


[14/24] olingo-odata2 git commit: [OLINGO-1253]Client Module for Olingo v2

Posted by ar...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/deserializer/JsonPropertyDeserializerTest.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/deserializer/JsonPropertyDeserializerTest.java b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/deserializer/JsonPropertyDeserializerTest.java
new file mode 100644
index 0000000..3a89af0
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/deserializer/JsonPropertyDeserializerTest.java
@@ -0,0 +1,834 @@
+/*******************************************************************************
+ * 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.client.core.ep.deserializer;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.UnsupportedEncodingException;
+import java.math.BigDecimal;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import org.apache.olingo.odata2.api.edm.EdmFacets;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeKind;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.client.api.ep.DeserializerProperties;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityComplexPropertyInfo;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityInfoAggregator;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityPropertyInfo;
+import org.apache.olingo.odata2.testutil.fit.BaseTest;
+import org.apache.olingo.odata2.testutil.mock.MockFacade;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import com.google.gson.stream.JsonReader;
+
+/**
+ *  
+ */
+public class JsonPropertyDeserializerTest extends BaseTest {
+  
+  @Rule
+  public ExpectedException expectedEx = ExpectedException.none();
+  
+  @Test
+  public void booleanSimpleProperty() throws Exception {
+    EdmProperty property = mock(EdmProperty.class);
+    when(property.getName()).thenReturn("Boolean");
+    when(property.isSimple()).thenReturn(true);
+    when(property.getType()).thenReturn(EdmSimpleTypeKind.Boolean.getEdmSimpleTypeInstance());
+
+    JsonReader reader = prepareReader("{\"Boolean\":true}");
+    final Map<String, Object> resultMap = execute(property, reader);
+    assertEquals(Boolean.TRUE, resultMap.get("Boolean"));
+  }
+
+  @Test
+  public void allNumberSimplePropertyKinds() throws Exception {
+    String simplePropertyJson = "{\"d\":{\"Age\":67}}";
+    EdmProperty edmProperty = mock(EdmProperty.class);
+    when(edmProperty.getName()).thenReturn("Age");
+    when(edmProperty.isSimple()).thenReturn(true);
+
+    // Byte
+    JsonReader reader = prepareReader(simplePropertyJson);
+    when(edmProperty.getType()).thenReturn(EdmSimpleTypeKind.Byte.getEdmSimpleTypeInstance());
+    Map<String, Object> resultMap = execute(edmProperty, reader);
+    assertEquals(Short.valueOf("67"), resultMap.get("Age"));
+
+    // SByte
+    reader = prepareReader(simplePropertyJson);
+    when(edmProperty.getType()).thenReturn(EdmSimpleTypeKind.SByte.getEdmSimpleTypeInstance());
+    resultMap = execute(edmProperty, reader);
+    assertEquals(Byte.valueOf("67"), resultMap.get("Age"));
+    // Int16
+    reader = prepareReader(simplePropertyJson);
+    when(edmProperty.getType()).thenReturn(EdmSimpleTypeKind.Int16.getEdmSimpleTypeInstance());
+    resultMap = execute(edmProperty, reader);
+    assertEquals(Short.valueOf("67"), resultMap.get("Age"));
+    // Int32
+    reader = prepareReader(simplePropertyJson);
+    when(edmProperty.getType()).thenReturn(EdmSimpleTypeKind.Int32.getEdmSimpleTypeInstance());
+    resultMap = execute(edmProperty, reader);
+    assertEquals(Integer.valueOf("67"), resultMap.get("Age"));
+  }
+
+  @Test
+  public void allStringSimplePropertyKinds() throws Exception {
+    EdmProperty edmProperty = mock(EdmProperty.class);
+    when(edmProperty.getName()).thenReturn("Name");
+    when(edmProperty.isSimple()).thenReturn(true);
+    String simplePropertyJson;
+
+    // DateTime
+    simplePropertyJson = "{\"d\":{\"Name\":\"\\/Date(915148800000)\\/\"}}";
+    JsonReader reader = prepareReader(simplePropertyJson);
+    when(edmProperty.getType()).thenReturn(EdmSimpleTypeKind.DateTime.getEdmSimpleTypeInstance());
+    Map<String, Object> resultMap = execute(edmProperty, reader);
+    Calendar entryDate = (Calendar) resultMap.get("Name");
+    assertEquals(Long.valueOf(915148800000l), Long.valueOf(entryDate.getTimeInMillis()));
+    // DateTimeOffset
+    simplePropertyJson = "{\"d\":{\"Name\":\"\\/Date(915148800000)\\/\"}}";
+    reader = prepareReader(simplePropertyJson);
+    when(edmProperty.getType()).thenReturn(EdmSimpleTypeKind.DateTime.getEdmSimpleTypeInstance());
+    resultMap = execute(edmProperty, reader);
+    entryDate = (Calendar) resultMap.get("Name");
+    assertEquals(Long.valueOf(915148800000l), Long.valueOf(entryDate.getTimeInMillis()));
+    // Decimal
+    simplePropertyJson = "{\"d\":{\"Name\":\"123456789\"}}";
+    reader = prepareReader(simplePropertyJson);
+    when(edmProperty.getType()).thenReturn(EdmSimpleTypeKind.Decimal.getEdmSimpleTypeInstance());
+    resultMap = execute(edmProperty, reader);
+    assertEquals(BigDecimal.valueOf(Long.valueOf("123456789")), resultMap.get("Name"));
+    // Double
+    simplePropertyJson = "{\"d\":{\"Name\":\"123456789\"}}";
+    reader = prepareReader(simplePropertyJson);
+    when(edmProperty.getType()).thenReturn(EdmSimpleTypeKind.Double.getEdmSimpleTypeInstance());
+    resultMap = execute(edmProperty, reader);
+    assertEquals(Double.valueOf("123456789"), resultMap.get("Name"));
+    // Double without "
+    simplePropertyJson = "{\"d\":{\"Name\":123456789}}";
+    reader = prepareReader(simplePropertyJson);
+    when(edmProperty.getType()).thenReturn(EdmSimpleTypeKind.Double.getEdmSimpleTypeInstance());
+    resultMap = execute(edmProperty, reader);
+    assertEquals(Double.valueOf("123456789"), resultMap.get("Name"));
+    // Int64
+    simplePropertyJson = "{\"d\":{\"Name\":\"123456789\"}}";
+    reader = prepareReader(simplePropertyJson);
+    when(edmProperty.getType()).thenReturn(EdmSimpleTypeKind.Int64.getEdmSimpleTypeInstance());
+    resultMap = execute(edmProperty, reader);
+    assertEquals(Long.valueOf("123456789"), resultMap.get("Name"));
+    // Single
+    simplePropertyJson = "{\"d\":{\"Name\":\"123456\"}}";
+    reader = prepareReader(simplePropertyJson);
+    when(edmProperty.getType()).thenReturn(EdmSimpleTypeKind.Single.getEdmSimpleTypeInstance());
+    resultMap = execute(edmProperty, reader);
+    assertEquals(Float.valueOf("123456"), resultMap.get("Name"));
+    // Single without "
+    simplePropertyJson = "{\"d\":{\"Name\":123456}}";
+    reader = prepareReader(simplePropertyJson);
+    when(edmProperty.getType()).thenReturn(EdmSimpleTypeKind.Single.getEdmSimpleTypeInstance());
+    resultMap = execute(edmProperty, reader);
+    assertEquals(Float.valueOf("123456"), resultMap.get("Name"));
+    // String
+    simplePropertyJson = "{\"d\":{\"Name\":\"123456789\"}}";
+    reader = prepareReader(simplePropertyJson);
+    when(edmProperty.getType()).thenReturn(EdmSimpleTypeKind.String.getEdmSimpleTypeInstance());
+    resultMap = execute(edmProperty, reader);
+    assertEquals("123456789", resultMap.get("Name"));
+    // Guid
+    simplePropertyJson = "{\"d\":{\"Name\":\"AABBCCDD-AABB-CCDD-EEFF-AABBCCDDEEFF\"}}";
+    reader = prepareReader(simplePropertyJson);
+    when(edmProperty.getType()).thenReturn(EdmSimpleTypeKind.Guid.getEdmSimpleTypeInstance());
+    resultMap = execute(edmProperty, reader);
+    assertEquals(UUID.fromString("aabbccdd-aabb-ccdd-eeff-aabbccddeeff"), resultMap.get("Name"));
+    // Binary
+    simplePropertyJson = "{\"d\":{\"Name\":\"qrvM\"}}";
+    reader = prepareReader(simplePropertyJson);
+    when(edmProperty.getType()).thenReturn(EdmSimpleTypeKind.Binary.getEdmSimpleTypeInstance());
+    resultMap = execute(edmProperty, reader);
+    assertTrue(Arrays.equals(new byte[] { (byte) 0xAA, (byte) 0xBB, (byte) 0xCC },
+        (byte[]) resultMap.get("Name")));
+    // Time
+    simplePropertyJson = "{\"d\":{\"Name\":\"PT23H32M3S\"}}";
+    reader = prepareReader(simplePropertyJson);
+    when(edmProperty.getType()).thenReturn(EdmSimpleTypeKind.Time.getEdmSimpleTypeInstance());
+    resultMap = execute(edmProperty, reader);
+    Calendar dateTime = Calendar.getInstance();
+    dateTime.clear();
+    dateTime.set(Calendar.HOUR_OF_DAY, 23);
+    dateTime.set(Calendar.MINUTE, 32);
+    dateTime.set(Calendar.SECOND, 3);
+    assertEquals(dateTime, resultMap.get("Name"));
+  }
+
+  @Test
+  public void simplePropertyOnOpenReader() throws Exception {
+    String simplePropertyJson = "{\"Name\":\"Team 1\"}";
+    JsonReader reader = prepareReader(simplePropertyJson);
+    EdmProperty edmProperty =
+        (EdmProperty) MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams").getEntityType()
+            .getProperty("Name");
+    EntityPropertyInfo entityPropertyInfo = EntityInfoAggregator.create(edmProperty);
+    reader.beginObject();
+    reader.nextName();
+
+    JsonPropertyDeserializer jpc = new JsonPropertyDeserializer();
+    Object value = jpc.readPropertyValue(reader, entityPropertyInfo, null, null);
+    assertEquals("Team 1", value);
+  }
+
+  @Test
+  public void veryLongStringStandalone() throws Exception {
+    char[] chars = new char[32768];
+    Arrays.fill(chars, 0, 32768, 'a');
+    String propertyValue = new String(chars);
+    String simplePropertyJson = "{\"d\":{\"Name\":\"" + propertyValue + "\"}}";
+    JsonReader reader = prepareReader(simplePropertyJson);
+    final EdmProperty edmProperty =
+        (EdmProperty) MockFacade.getMockEdm().getEntityType("RefScenario", "Room").getProperty("Name");
+
+    DeserializerProperties readProperties = mock(DeserializerProperties.class);
+    when(readProperties.getTypeMappings()).thenReturn(null);
+    Map<String, Object> resultMap =
+        new JsonPropertyDeserializer().readPropertyStandalone(reader, edmProperty, readProperties);
+
+    assertEquals(propertyValue, resultMap.get("Name"));
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void simplePropertyViolatingValidation() throws Exception {
+    EdmProperty property = (EdmProperty) MockFacade.getMockEdm().getEntityType("RefScenario", "Room")
+        .getProperty("Name");
+    EdmFacets facets = mock(EdmFacets.class);
+    when(facets.getMaxLength()).thenReturn(10);
+    when(property.getFacets()).thenReturn(facets);
+    new JsonPropertyDeserializer().readPropertyStandalone(prepareReader("{\"Name\":\"TooLongName\"}"), property, null);
+  }
+
+  @Test
+  public void simplePropertyIgnoringValidation() throws Exception {
+    EdmProperty property = (EdmProperty) MockFacade.getMockEdm().getEntityType("RefScenario", "Room")
+        .getProperty("Name");
+    EdmFacets facets = mock(EdmFacets.class);
+    when(facets.getMaxLength()).thenReturn(10);
+    when(property.getFacets()).thenReturn(facets);
+    final DeserializerProperties readProperties = mock(DeserializerProperties.class);
+    final Map<String, Object> resultMap = new JsonPropertyDeserializer()
+        .readPropertyStandalone(prepareReader("{\"Name\":\"TooLongName\"}"), property, readProperties);
+    assertTrue(resultMap.containsKey("Name"));
+    assertEquals("TooLongName", resultMap.get("Name"));
+  }
+
+  @Test
+  public void simplePropertyNull() throws Exception {
+    JsonReader reader = prepareReader("{\"Name\":null}");
+    final EdmProperty property =
+        (EdmProperty) MockFacade.getMockEdm().getEntityType("RefScenario", "Room").getProperty("Name");
+    final Map<String, Object> resultMap = new JsonPropertyDeserializer().readPropertyStandalone(reader, property, null);
+    assertTrue(resultMap.containsKey("Name"));
+    assertNull(resultMap.get("Name"));
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void simplePropertyNullValueNotAllowed() throws Exception {
+    JsonReader reader = prepareReader("{\"Age\":null}");
+    EdmProperty property =
+        (EdmProperty) MockFacade.getMockEdm().getEntityType("RefScenario", "Employee").getProperty("Age");
+    EdmFacets facets = mock(EdmFacets.class);
+    when(facets.isNullable()).thenReturn(false);
+    when(property.getFacets()).thenReturn(facets);
+
+    new JsonPropertyDeserializer().readPropertyStandalone(reader, property, null);
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void simplePropertyInvalidName() throws Exception {
+    EdmProperty property = mock(EdmProperty.class);
+    when(property.getName()).thenReturn("property-name");
+    when(property.isSimple()).thenReturn(true);
+    when(property.getType()).thenReturn(EdmSimpleTypeKind.Boolean.getEdmSimpleTypeInstance());
+
+    JsonReader reader = prepareReader("{\"Boolean\":true}");
+    execute(property, reader);
+    expectedEx.expect(RuntimeException.class);
+    expectedEx.expectMessage("'property-name' name pattern not valid.");
+  }
+  
+  @Test
+  public void simplePropertyWithNullMappingStandalone() throws Exception {
+    String simplePropertyJson = "{\"d\":{\"Age\":67}}";
+    JsonReader reader = prepareReader(simplePropertyJson);
+    final EdmProperty edmProperty =
+        (EdmProperty) MockFacade.getMockEdm().getEntityType("RefScenario", "Employee").getProperty("Age");
+
+    DeserializerProperties readProperties = mock(DeserializerProperties.class);
+    when(readProperties.getTypeMappings()).thenReturn(null);
+    Map<String, Object> resultMap =
+        new JsonPropertyDeserializer().readPropertyStandalone(reader, edmProperty, readProperties);
+
+    assertEquals(Integer.valueOf(67), resultMap.get("Age"));
+  }
+
+  @Test
+  public void simplePropertyWithNullMappingStandaloneWithoutD() throws Exception {
+    String simplePropertyJson = "{\"Age\":67}";
+    JsonReader reader = prepareReader(simplePropertyJson);
+    final EdmProperty edmProperty =
+        (EdmProperty) MockFacade.getMockEdm().getEntityType("RefScenario", "Employee").getProperty("Age");
+
+    DeserializerProperties readProperties = mock(DeserializerProperties.class);
+    when(readProperties.getTypeMappings()).thenReturn(null);
+    Map<String, Object> resultMap =
+        new JsonPropertyDeserializer().readPropertyStandalone(reader, edmProperty, readProperties);
+
+    assertEquals(Integer.valueOf(67), resultMap.get("Age"));
+  }
+
+  @Test
+  public void simplePropertyWithEmptyMappingStandalone() throws Exception {
+    String simplePropertyJson = "{\"d\":{\"Age\":67}}";
+    JsonReader reader = prepareReader(simplePropertyJson);
+    final EdmProperty edmProperty =
+        (EdmProperty) MockFacade.getMockEdm().getEntityType("RefScenario", "Employee").getProperty("Age");
+
+    DeserializerProperties readProperties = mock(DeserializerProperties.class);
+    when(readProperties.getTypeMappings()).thenReturn(new HashMap<String, Object>());
+    Map<String, Object> resultMap =
+        new JsonPropertyDeserializer().readPropertyStandalone(reader, edmProperty, readProperties);
+
+    assertEquals(Integer.valueOf(67), resultMap.get("Age"));
+  }
+
+  @Test
+  public void simplePropertyWithStringToLongMappingStandalone() throws Exception {
+    String simplePropertyJson = "{\"d\":{\"Age\":67}}";
+    JsonReader reader = prepareReader(simplePropertyJson);
+    final EdmProperty edmProperty =
+        (EdmProperty) MockFacade.getMockEdm().getEntityType("RefScenario", "Employee").getProperty("Age");
+
+    DeserializerProperties readProperties = mock(DeserializerProperties.class);
+    Map<String, Object> typeMappings = new HashMap<String, Object>();
+    typeMappings.put("Age", Integer.class);
+    when(readProperties.getTypeMappings()).thenReturn(typeMappings);
+    Map<String, Object> resultMap =
+        new JsonPropertyDeserializer().readPropertyStandalone(reader, edmProperty, readProperties);
+
+    assertEquals(Integer.valueOf(67), resultMap.get("Age"));
+  }
+
+  @Test
+  public void simplePropertyWithStringToNullMappingStandalone() throws Exception {
+    String simplePropertyJson = "{\"d\":{\"Age\":67}}";
+    JsonReader reader = prepareReader(simplePropertyJson);
+    final EdmProperty edmProperty =
+        (EdmProperty) MockFacade.getMockEdm().getEntityType("RefScenario", "Employee").getProperty("Age");
+
+    DeserializerProperties readProperties = mock(DeserializerProperties.class);
+    Map<String, Object> typeMappings = new HashMap<String, Object>();
+    typeMappings.put("Age", null);
+    when(readProperties.getTypeMappings()).thenReturn(typeMappings);
+    Map<String, Object> resultMap =
+        new JsonPropertyDeserializer().readPropertyStandalone(reader, edmProperty, readProperties);
+
+    assertEquals(Integer.valueOf(67), resultMap.get("Age"));
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void noContent() throws Exception {
+    final EdmProperty property =
+        (EdmProperty) MockFacade.getMockEdm().getEntityType("RefScenario", "Employee").getProperty("Age");
+    JsonReader reader = prepareReader("{}");
+    new JsonPropertyDeserializer().readPropertyStandalone(reader, property, null);
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void simplePropertyUnfinished() throws Exception {
+    final EdmProperty property =
+        (EdmProperty) MockFacade.getMockEdm().getEntityType("RefScenario", "Employee").getProperty("Age");
+    JsonReader reader = prepareReader("{\"Age\":67");
+    new JsonPropertyDeserializer().readPropertyStandalone(reader, property, null);
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void simplePropertInvalidName() throws Exception {
+    String simplePropertyJson = "{\"d\":{\"Invalid\":67}}";
+    JsonReader reader = prepareReader(simplePropertyJson);
+    final EdmProperty edmProperty =
+        (EdmProperty) MockFacade.getMockEdm().getEntityType("RefScenario", "Employee").getProperty("Age");
+
+    new JsonPropertyDeserializer().readPropertyStandalone(reader, edmProperty, null);
+  }
+
+  @Test
+  public void complexPropertyWithStringToStringMappingStandalone() throws Exception {
+    final String complexPropertyJson =
+        "{\"d\":{\"City\":{\"__metadata\":{\"type\":\"RefScenario.c_City\"}," +
+            "\"PostalCode\":\"69124\",\"CityName\":\"Heidelberg\"}}}";
+    JsonReader reader = prepareReader(complexPropertyJson);
+    final EdmProperty property =
+        (EdmProperty) MockFacade.getMockEdm().getComplexType("RefScenario", "c_Location").getProperty("City");
+
+    DeserializerProperties readProperties = mock(DeserializerProperties.class);
+    Map<String, Object> innerMappings = new HashMap<String, Object>();
+    innerMappings.put("PostalCode", String.class);
+    Map<String, Object> typeMappings = new HashMap<String, Object>();
+    typeMappings.put("City", innerMappings);
+    when(readProperties.getTypeMappings()).thenReturn(typeMappings);
+    Map<String, Object> result = new JsonPropertyDeserializer().
+        readPropertyStandalone(reader, property, readProperties);
+
+    assertEquals(1, result.size());
+    @SuppressWarnings("unchecked")
+    Map<String, Object> innerResult = (Map<String, Object>) result.get("City");
+    assertEquals("Heidelberg", innerResult.get("CityName"));
+    assertEquals("69124", innerResult.get("PostalCode"));
+  }
+
+  @Test
+  public void deepComplexPropertyWithStringToStringMappingStandalone() throws Exception {
+    final String complexPropertyJson =
+        "{\"d\":{\"Location\":{\"__metadata\":{\"type\":\"RefScenario.c_Location\"}," +
+            "\"City\":{\"__metadata\":{\"type\":\"RefScenario.c_City\"},\"PostalCode\":\"69124\"," +
+            "\"CityName\":\"Heidelberg\"},\"Country\":\"Germany\"}}}";
+    JsonReader reader = prepareReader(complexPropertyJson);
+    EdmProperty edmProperty =
+        (EdmProperty) MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees").getEntityType()
+            .getProperty("Location");
+
+    DeserializerProperties readProperties = mock(DeserializerProperties.class);
+    Map<String, Object> cityMappings = new HashMap<String, Object>();
+    cityMappings.put("PostalCode", String.class);
+    Map<String, Object> locationMappings = new HashMap<String, Object>();
+    locationMappings.put("City", cityMappings);
+    Map<String, Object> mappings = new HashMap<String, Object>();
+    mappings.put("Location", locationMappings);
+    when(readProperties.getTypeMappings()).thenReturn(mappings);
+
+    final Map<String, Object> result =
+        new JsonPropertyDeserializer().readPropertyStandalone(reader, edmProperty, readProperties);
+
+    assertEquals(1, result.size());
+    @SuppressWarnings("unchecked")
+    Map<String, Object> locationResult = (Map<String, Object>) result.get("Location");
+    assertEquals(2, locationResult.size());
+    assertEquals("Germany", locationResult.get("Country"));
+    @SuppressWarnings("unchecked")
+    Map<String, Object> innerResult = (Map<String, Object>) locationResult.get("City");
+    assertEquals(2, innerResult.size());
+    assertEquals("Heidelberg", innerResult.get("CityName"));
+    assertEquals("69124", innerResult.get("PostalCode"));
+  }
+
+  @Test
+  public void complexPropertyOnOpenReader() throws Exception {
+    final String complexPropertyJson =
+        "{\"__metadata\":{\"type\":\"RefScenario.c_City\"},\"PostalCode\":\"69124\",\"CityName\":\"Heidelberg\"}";
+    JsonReader reader = prepareReader(complexPropertyJson);
+    final EdmProperty property =
+        (EdmProperty) MockFacade.getMockEdm().getComplexType("RefScenario", "c_Location").getProperty("City");
+    EntityComplexPropertyInfo entityPropertyInfo = (EntityComplexPropertyInfo) EntityInfoAggregator.create(property);
+
+    JsonPropertyDeserializer jpc = new JsonPropertyDeserializer();
+    @SuppressWarnings("unchecked")
+    Map<String, Object> result = (Map<String, Object>) jpc.readPropertyValue(reader, entityPropertyInfo, null, null);
+
+    assertEquals(2, result.size());
+    assertEquals("Heidelberg", result.get("CityName"));
+    assertEquals("69124", result.get("PostalCode"));
+  }
+
+  @Test
+  public void complexPropertyOnOpenReaderWithNoMetadata() throws Exception {
+    final String complexPropertyJson = "{\"PostalCode\":\"69124\",\"CityName\":\"Heidelberg\"}";
+    JsonReader reader = prepareReader(complexPropertyJson);
+    final EdmProperty property =
+        (EdmProperty) MockFacade.getMockEdm().getComplexType("RefScenario", "c_Location").getProperty("City");
+    EntityComplexPropertyInfo entityPropertyInfo = (EntityComplexPropertyInfo) EntityInfoAggregator.create(property);
+
+    JsonPropertyDeserializer jpc = new JsonPropertyDeserializer();
+    @SuppressWarnings("unchecked")
+    Map<String, Object> result = (Map<String, Object>) jpc.readPropertyValue(reader, entityPropertyInfo, null, null);
+
+    assertEquals(2, result.size());
+    assertEquals("Heidelberg", result.get("CityName"));
+    assertEquals("69124", result.get("PostalCode"));
+  }
+
+  @Test
+  public void deepComplexPropertyOnOpenReader() throws Exception {
+    final String complexPropertyJson =
+        "{\"__metadata\":{\"type\":\"RefScenario.c_Location\"}," +
+            "\"City\":{\"__metadata\":{\"type\":\"RefScenario.c_City\"},\"PostalCode\":\"69124\"," +
+            "\"CityName\":\"Heidelberg\"},\"Country\":\"Germany\"}";
+    JsonReader reader = prepareReader(complexPropertyJson);
+    EdmProperty edmProperty =
+        (EdmProperty) MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees").getEntityType()
+            .getProperty("Location");
+    EntityComplexPropertyInfo entityPropertyInfo = (EntityComplexPropertyInfo) EntityInfoAggregator.create(edmProperty);
+
+    JsonPropertyDeserializer jpc = new JsonPropertyDeserializer();
+    @SuppressWarnings("unchecked")
+    Map<String, Object> result = (Map<String, Object>) jpc.readPropertyValue(reader, entityPropertyInfo, null, null);
+
+    assertEquals(2, result.size());
+    assertEquals("Germany", result.get("Country"));
+    @SuppressWarnings("unchecked")
+    Map<String, Object> innerResult = (Map<String, Object>) result.get("City");
+    assertEquals(2, innerResult.size());
+    assertEquals("Heidelberg", innerResult.get("CityName"));
+    assertEquals("69124", innerResult.get("PostalCode"));
+  }
+
+  @Test
+  public void simplePropertyStandalone() throws Exception {
+    String simplePropertyJson = "{\"d\":{\"Name\":\"Team 1\"}}";
+    EdmProperty edmProperty =
+        (EdmProperty) MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams").getEntityType()
+            .getProperty("Name");
+    JsonReader reader = prepareReader(simplePropertyJson);
+
+    Map<String, Object> result = new JsonPropertyDeserializer().readPropertyStandalone(reader, edmProperty, null);
+    assertEquals("Team 1", result.get("Name"));
+  }
+
+  @Test
+  public void complexPropertyStandalone() throws Exception {
+    final String complexPropertyJson =
+        "{\"d\":{\"City\":{\"__metadata\":{\"type\":\"RefScenario.c_City\"}," +
+            "\"PostalCode\":\"69124\",\"CityName\":\"Heidelberg\"}}}";
+    JsonReader reader = prepareReader(complexPropertyJson);
+    final EdmProperty property =
+        (EdmProperty) MockFacade.getMockEdm().getComplexType("RefScenario", "c_Location").getProperty("City");
+
+    final Map<String, Object> result = new JsonPropertyDeserializer().readPropertyStandalone(reader, property, null);
+
+    assertEquals(1, result.size());
+    @SuppressWarnings("unchecked")
+    Map<String, Object> innerResult = (Map<String, Object>) result.get("City");
+    assertEquals("Heidelberg", innerResult.get("CityName"));
+    assertEquals("69124", innerResult.get("PostalCode"));
+  }
+
+  @Test
+  public void deepComplexPropertyStandalone() throws Exception {
+    final String complexPropertyJson =
+        "{\"d\":{\"Location\":{\"__metadata\":{\"type\":\"RefScenario.c_Location\"}," +
+            "\"City\":{\"__metadata\":{\"type\":\"RefScenario.c_City\"},\"PostalCode\":\"69124\"," +
+            "\"CityName\":\"Heidelberg\"},\"Country\":\"Germany\"}}}";
+    JsonReader reader = prepareReader(complexPropertyJson);
+    EdmProperty edmProperty =
+        (EdmProperty) MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees").getEntityType()
+            .getProperty("Location");
+
+    JsonPropertyDeserializer jpc = new JsonPropertyDeserializer();
+    Map<String, Object> result = jpc.readPropertyStandalone(reader, edmProperty, null);
+
+    assertEquals(1, result.size());
+    @SuppressWarnings("unchecked")
+    Map<String, Object> locationResult = (Map<String, Object>) result.get("Location");
+    assertEquals(2, locationResult.size());
+    assertEquals("Germany", locationResult.get("Country"));
+    @SuppressWarnings("unchecked")
+    Map<String, Object> innerResult = (Map<String, Object>) locationResult.get("City");
+    assertEquals(2, innerResult.size());
+    assertEquals("Heidelberg", innerResult.get("CityName"));
+    assertEquals("69124", innerResult.get("PostalCode"));
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void complexPropertyWithInvalidChild() throws Exception {
+    String cityProperty = "{\"d\":{\"City\":{\"Invalid\":\"69124\",\"CityName\":\"Heidelberg\"}}}";
+    JsonReader reader = prepareReader(cityProperty);
+    final EdmProperty property =
+        (EdmProperty) MockFacade.getMockEdm().getComplexType("RefScenario", "c_Location").getProperty("City");
+
+    new JsonPropertyDeserializer().readPropertyStandalone(reader, property, null);
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void complexPropertyWithInvalidName() throws Exception {
+    String cityProperty = "{\"d\":{\"Invalid\":{\"PostalCode\":\"69124\",\"CityName\":\"Heidelberg\"}}}";
+    JsonReader reader = prepareReader(cityProperty);
+    final EdmProperty property =
+        (EdmProperty) MockFacade.getMockEdm().getComplexType("RefScenario", "c_Location").getProperty("City");
+
+    new JsonPropertyDeserializer().readPropertyStandalone(reader, property, null);
+  }
+
+  @Test
+  public void complexPropertyNull() throws Exception {
+    final String locationProperty = "{\"Location\":null}";
+    JsonReader reader = prepareReader(locationProperty);
+    final EdmProperty property =
+        (EdmProperty) MockFacade.getMockEdm().getDefaultEntityContainer().
+        getEntitySet("Employees").getEntityType()
+            .getProperty("Location");
+
+    final Map<String, Object> propertyData = new JsonPropertyDeserializer().
+        readPropertyStandalone(reader, property, null);
+    assertNotNull(propertyData);
+    assertEquals(1, propertyData.size());
+    assertTrue(propertyData.containsKey("Location"));
+    assertNull(propertyData.get("Location"));
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void complexPropertyNullValueNotAllowed() throws Exception {
+    final String locationProperty = "{\"Location\":null}";
+    JsonReader reader = prepareReader(locationProperty);
+    EdmProperty property =
+        (EdmProperty) MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees").getEntityType()
+            .getProperty("Location");
+    EdmFacets facets = mock(EdmFacets.class);
+    when(facets.isNullable()).thenReturn(false);
+    when(property.getFacets()).thenReturn(facets);
+
+    new JsonPropertyDeserializer().readPropertyStandalone(reader, property, null);
+  }
+
+  @Test
+  public void complexPropertyNullValueNotAllowedButNotValidated() throws Exception {
+    final EdmProperty property = (EdmProperty) MockFacade.getMockEdm().getDefaultEntityContainer()
+        .getEntitySet("Employees").getEntityType().getProperty("Location");
+    EdmFacets facets = mock(EdmFacets.class);
+    when(facets.isNullable()).thenReturn(false);
+    when(property.getFacets()).thenReturn(facets);
+    final DeserializerProperties readProperties = mock(DeserializerProperties.class);
+
+    final Map<String, Object> propertyData = new JsonPropertyDeserializer()
+        .readPropertyStandalone(prepareReader("{\"Location\":null}"), property, readProperties);
+    assertNotNull(propertyData);
+    assertEquals(1, propertyData.size());
+    assertTrue(propertyData.containsKey("Location"));
+    assertNull(propertyData.get("Location"));
+  }
+
+  @Test
+  public void complexPropertyEmpty() throws Exception {
+    final String cityProperty = "{\"d\":{\"City\":{}}}";
+    JsonReader reader = prepareReader(cityProperty);
+    final EdmProperty property =
+        (EdmProperty) MockFacade.getMockEdm().
+        getComplexType("RefScenario", "c_Location").getProperty("City");
+
+    final Map<String, Object> propertyData = new JsonPropertyDeserializer().
+        readPropertyStandalone(reader, property, null);
+    assertNotNull(propertyData);
+    assertEquals(1, propertyData.size());
+    assertNotNull(propertyData.get("City"));
+    @SuppressWarnings("unchecked")
+    final Map<String, Object> innerMap = (Map<String, Object>) propertyData.get("City");
+    assertTrue(innerMap.isEmpty());
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void complexPropertyMetadataInvalidTag() throws Exception {
+    String complexPropertyJson =
+        "{\"__metadata\":{\"invalid\":\"RefScenario.c_City\"},"
+        + "\"PostalCode\":\"69124\",\"CityName\":\"Heidelberg\"}";
+    JsonReader reader = prepareReader(complexPropertyJson);
+    final EdmProperty property =
+        (EdmProperty) MockFacade.getMockEdm().getComplexType
+        ("RefScenario", "c_Location").getProperty("City");
+    EntityComplexPropertyInfo entityPropertyInfo = (EntityComplexPropertyInfo) 
+        EntityInfoAggregator.create(property);
+
+    new JsonPropertyDeserializer().readPropertyValue(reader, entityPropertyInfo, null, null);
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void complexPropertyMetadataInvalidTypeContent() throws Exception {
+    String complexPropertyJson =
+        "{\"__metadata\":{\"type\":\"Invalid\"},\"PostalCode\":\"69124\",\"CityName\":\"Heidelberg\"}";
+    JsonReader reader = prepareReader(complexPropertyJson);
+    final EdmProperty property =
+        (EdmProperty) MockFacade.getMockEdm().getComplexType
+        ("RefScenario", "c_Location").getProperty("City");
+    EntityComplexPropertyInfo entityPropertyInfo = (EntityComplexPropertyInfo) 
+        EntityInfoAggregator.create(property);
+
+    new JsonPropertyDeserializer().readPropertyValue(reader, entityPropertyInfo, null, null);
+  }
+
+  private JsonReader prepareReader(final String json) throws UnsupportedEncodingException {
+    InputStream jsonStream = createContentAsStream(json);
+    JsonReader reader = new JsonReader(new InputStreamReader(jsonStream));
+    return reader;
+  }
+
+  private Map<String, Object> execute(final EdmProperty edmProperty, final JsonReader reader)
+      throws EntityProviderException {
+    JsonPropertyDeserializer jpc = new JsonPropertyDeserializer();
+    Map<String, Object> resultMap = jpc.readPropertyStandalone(reader, edmProperty, null);
+    return resultMap;
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void invalidDoubleClosingBrackets() throws Exception {
+    String simplePropertyJson = "{\"d\":{\"Name\":\"Team 1\"}}}";
+    EdmProperty edmProperty =
+        (EdmProperty) MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams").getEntityType()
+            .getProperty("Name");
+    JsonReader reader = prepareReader(simplePropertyJson);
+
+    new JsonPropertyDeserializer().readPropertyStandalone(reader, edmProperty, null);
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void invalidDoubleClosingBracketsWithoutD() throws Exception {
+    String simplePropertyJson = "{\"Name\":\"Team 1\"}}";
+    EdmProperty edmProperty =
+        (EdmProperty) MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams").getEntityType()
+            .getProperty("Name");
+    JsonReader reader = prepareReader(simplePropertyJson);
+
+    new JsonPropertyDeserializer().readPropertyStandalone(reader, edmProperty, null);
+  }
+
+  @Test
+  public void collectionEmpty() throws Exception {
+    final EntityPropertyInfo info = EntityInfoAggregator.create(
+        MockFacade.getMockEdm().getDefaultEntityContainer().getFunctionImport("AllUsedRoomIds"));
+    List<?> collection = new JsonPropertyDeserializer().readCollection(prepareReader("[]"), info, null);
+    assertNotNull(collection);
+    assertTrue(collection.isEmpty());
+
+    collection = new JsonPropertyDeserializer().readCollection(prepareReader("{\"d\":[]}"), info, null);
+    assertNotNull(collection);
+    assertTrue(collection.isEmpty());
+
+    collection = new JsonPropertyDeserializer().readCollection(prepareReader("{\"results\":[]}"), info, null);
+    assertNotNull(collection);
+    assertTrue(collection.isEmpty());
+
+    collection = new JsonPropertyDeserializer().readCollection(prepareReader("{\"d\":{\"results\":[]}}"), info, null);
+    assertNotNull(collection);
+    assertTrue(collection.isEmpty());
+  }
+
+  @Test
+  public void collectionSimple() throws Exception {
+    final EntityPropertyInfo info = EntityInfoAggregator.create(
+        MockFacade.getMockEdm().getDefaultEntityContainer().getFunctionImport("AllUsedRoomIds"));
+    List<?> collection = new JsonPropertyDeserializer().readCollection(prepareReader("[\"1\",\"42\"]"), info, null);
+    assertNotNull(collection);
+    assertEquals(Arrays.asList("1", "42"), collection);
+  }
+
+  @Test
+  public void collectionSimpleWithMetadata() throws Exception {
+    final EntityPropertyInfo info = EntityInfoAggregator.create(
+        MockFacade.getMockEdm().getDefaultEntityContainer().getFunctionImport("AllUsedRoomIds"));
+    List<?> collection = new JsonPropertyDeserializer().readCollection(prepareReader(
+        "{\"__metadata\":{\"type\":\"Collection(Edm.String)\"},\"results\":[\"1\",\"42\"]}"),
+        info, null);
+    assertNotNull(collection);
+    assertEquals(Arrays.asList("1", "42"), collection);
+  }
+
+  @Test
+  public void collectionSimpleWithMapping() throws Exception {
+    final EntityPropertyInfo info = EntityInfoAggregator.create(
+        MockFacade.getMockEdm().getDefaultEntityContainer().getFunctionImport("AllUsedRoomIds"));
+    DeserializerProperties readProperties = mock(DeserializerProperties.class);
+    when(readProperties.getTypeMappings()).thenReturn(
+        Collections.<String, Object> singletonMap("AllUsedRoomIds", String.class));
+    List<?> collection = new JsonPropertyDeserializer().readCollection(prepareReader("[\"1\",\"42\"]"), info,
+        readProperties);
+    assertNotNull(collection);
+    assertEquals(Arrays.asList("1", "42"), collection);
+  }
+
+  @Test
+  public void collectionComplex() throws Exception {
+    final EntityPropertyInfo info = EntityInfoAggregator.create(
+        MockFacade.getMockEdm().getDefaultEntityContainer().getFunctionImport("AllLocations"));
+    DeserializerProperties readProperties = mock(DeserializerProperties.class);
+    final Map<String, Object> mappings = Collections.<String, Object> singletonMap("Location",
+        Collections.<String, Object> singletonMap("City",
+            Collections.<String, Object> singletonMap("PostalCode", String.class)));
+    when(readProperties.getTypeMappings()).thenReturn(mappings);
+    List<?> collection = new JsonPropertyDeserializer().readCollection(prepareReader(
+        "{\"__metadata\":{\"type\":\"Collection(RefScenario.c_Location)\"},"
+            + "\"results\":["
+            + "{\"City\":{\"PostalCode\":\"69124\",\"CityName\":\"Heidelberg\"},\"Country\":\"Germany\"},"
+            + "{\"City\":{\"PostalCode\":\"69190\",\"CityName\":\"Walldorf\"},\"Country\":\"Germany\"}]}"),
+        info, readProperties);
+    assertNotNull(collection);
+    assertEquals(2, collection.size());
+    @SuppressWarnings("unchecked")
+    final Map<String, Object> secondLocation = (Map<String, Object>) collection.get(1);
+    assertEquals("Germany", secondLocation.get("Country"));
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void collectionUnfinished() throws Exception {
+    final EntityPropertyInfo info = EntityInfoAggregator.create(
+        MockFacade.getMockEdm().getDefaultEntityContainer().getFunctionImport("AllUsedRoomIds"));
+    new JsonPropertyDeserializer().readCollection(prepareReader("[\"1\""), info, null);
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void collectionWithoutClosing() throws Exception {
+    final EntityPropertyInfo info = EntityInfoAggregator.create(
+        MockFacade.getMockEdm().getDefaultEntityContainer().getFunctionImport("AllUsedRoomIds"));
+    new JsonPropertyDeserializer().readCollection(prepareReader("{\"results\":[]"), info, null);
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void collectionWithWrongTag() throws Exception {
+    final EntityPropertyInfo info = EntityInfoAggregator.create(
+        MockFacade.getMockEdm().getDefaultEntityContainer().getFunctionImport("AllUsedRoomIds"));
+    new JsonPropertyDeserializer().readCollection(prepareReader("{\"something\":[]}"), info, null);
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void collectionWithWrongInnerTag() throws Exception {
+    final EntityPropertyInfo info = EntityInfoAggregator.create(
+        MockFacade.getMockEdm().getDefaultEntityContainer().getFunctionImport("AllUsedRoomIds"));
+    new JsonPropertyDeserializer().readCollection(prepareReader("{\"d\":{\"something\":[]}}"), info, null);
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void collectionWithTrailing() throws Exception {
+    final EntityPropertyInfo info = EntityInfoAggregator.create(
+        MockFacade.getMockEdm().getDefaultEntityContainer().getFunctionImport("AllUsedRoomIds"));
+    new JsonPropertyDeserializer().readCollection(prepareReader("{\"results\":[],\"a\":0}"), info, null);
+  }
+
+  private InputStream createContentAsStream(final String json) throws UnsupportedEncodingException {
+    return new ByteArrayInputStream(json.getBytes("UTF-8"));
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/deserializer/XMLMetadataFunctionImportDeserializerTest.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/deserializer/XMLMetadataFunctionImportDeserializerTest.java b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/deserializer/XMLMetadataFunctionImportDeserializerTest.java
new file mode 100644
index 0000000..c2870a4
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/deserializer/XMLMetadataFunctionImportDeserializerTest.java
@@ -0,0 +1,583 @@
+package org.apache.olingo.odata2.client.core.ep.deserializer;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.List;
+
+import javax.xml.stream.XMLStreamException;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmAnnotationAttribute;
+import org.apache.olingo.odata2.api.edm.EdmAnnotationElement;
+import org.apache.olingo.odata2.api.edm.EdmAnnotations;
+import org.apache.olingo.odata2.api.edm.EdmEntityContainer;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmFunctionImport;
+import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
+import org.apache.olingo.odata2.api.edm.EdmParameter;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.client.api.edm.EdmDataServices;
+import org.apache.olingo.odata2.client.api.edm.EdmSchema;
+import org.junit.Test;
+
+public class XMLMetadataFunctionImportDeserializerTest {
+  private static final String NAMESPACE = "RefScenario";
+  private static final String NAMESPACE2 = "RefScenario2";
+  
+  private final String[] propertyNames = { "EmployeeId", "EmployeeName", "Location" };
+  
+  @Test
+  public void testFunctionImport() throws XMLStreamException, 
+  EntityProviderException, EdmException, UnsupportedEncodingException {
+    final String xmWithEntityContainer =
+        "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\""
+            + Edm.NAMESPACE_EDMX_2007_06
+            + "\">"
+            + "<edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\""
+            + Edm.NAMESPACE_M_2007_08
+            + "\">"
+            + "<Schema Namespace=\""
+            + NAMESPACE
+            + "\" xmlns=\""
+            + Edm.NAMESPACE_EDM_2008_09
+            + "\">"
+            + "<EntityType Name= \"Employee\" m:HasStream=\"true\">"
+            + "<Key><PropertyRef Name=\"EmployeeId\"/></Key>"
+            + "<Property Name=\""
+            + propertyNames[0]
+            + "\" Type=\"Edm.String\" Nullable=\"false\"/>"
+            + "<Property Name=\""
+            + propertyNames[1]
+            + "\" Type=\"Edm.String\" m:FC_TargetPath=\"SyndicationTitle\"/>"
+            + "</EntityType>"
+            + "<EntityContainer Name=\"Container1\" m:IsDefaultEntityContainer=\"true\">"
+            + "<EntitySet Name=\"Employees\" EntityType=\"RefScenario.Employee\"/>"
+            + "<FunctionImport Name=\"EmployeeSearch\" ReturnType=\"Collection(RefScenario.Employee)\" " +
+            "EntitySet=\"Employees\" m:HttpMethod=\"GET\">"
+            + "<Parameter Name=\"q1\" Type=\"Edm.String\" Nullable=\"true\" />"
+            + "<Parameter Name=\"q2\" Type=\"Edm.Int32\" Nullable=\"false\" />"
+            + "</FunctionImport>"
+            + "<FunctionImport Name=\"RoomSearch\" ReturnType=\"Collection(RefScenario.Employee)\" " +
+            "EntitySet=\"Employees\" m:HttpMethod=\"GET\">"
+            + "<Parameter Name=\"q1\" Type=\"Edm.String\" Nullable=\"true\" Mode=\"In\"/>"
+            + "<Parameter Name=\"q2\" Type=\"Edm.Int32\" Nullable=\"false\" />"
+            + "</FunctionImport>"
+            + "<FunctionImport Name=\"NoParamters\" ReturnType=\"Collection(RefScenario.Employee)\" " +
+            "EntitySet=\"Employees\" m:HttpMethod=\"GET\">"
+            + "</FunctionImport>"
+            + "<FunctionImport Name=\"NoReturn\" " +
+            "EntitySet=\"Rooms\" m:HttpMethod=\"GET\"/>"
+            + "<FunctionImport Name=\"SingleRoomReturnType\" ReturnType=\"RefScenario.Employee\" " +
+            "EntitySet=\"Employees\" m:HttpMethod=\"GET\">"
+            + "</FunctionImport>"
+            + "</EntityContainer>" + "</Schema>" + "</edmx:DataServices>" + "</edmx:Edmx>";
+    XmlMetadataDeserializer parser = new XmlMetadataDeserializer();
+    InputStream reader = createStreamReader(xmWithEntityContainer);
+    EdmDataServices result = parser.readMetadata(reader, true);
+    for (EdmSchema schema : result.getEdm().getSchemas()) {
+      for (EdmEntityContainer container : schema.getEntityContainers()) {
+        assertEquals("Container1", container.getName());
+        assertEquals(Boolean.TRUE, container.isDefaultEntityContainer());
+
+        EdmFunctionImport functionImport1 = container.getFunctionImport("EmployeeSearch");
+
+        assertEquals("EmployeeSearch", functionImport1.getName());
+        checkParameters1(functionImport1);
+
+        EdmFunctionImport functionImport2 = container.getFunctionImport("RoomSearch");
+        assertEquals("RoomSearch", functionImport2.getName());
+        assertEquals("Employees", functionImport2.getEntitySet().getName());
+        assertEquals(NAMESPACE, functionImport2.getReturnType().getType().getNamespace());
+        assertEquals("Employee", functionImport2.getReturnType().getName());
+        assertEquals(EdmMultiplicity.MANY, functionImport2.getReturnType().getMultiplicity());
+        assertEquals("GET", functionImport2.getHttpMethod());
+        List<String> parameterNames = (List<String>) functionImport2.getParameterNames();
+        
+        assertEquals(2, parameterNames.size());
+
+        EdmParameter edmParam = functionImport2.getParameter(parameterNames.get(0));
+        assertEquals("q1", parameterNames.get(0));
+        assertEquals("String", edmParam.getType().getName());
+        assertEquals(Boolean.TRUE, edmParam.getFacets().isNullable());
+        
+        edmParam = functionImport2.getParameter(parameterNames.get(1));
+        assertEquals("q2", parameterNames.get(1));
+        assertEquals("Int32", edmParam.getType().getName());
+        assertEquals(Boolean.FALSE, edmParam.getFacets().isNullable());
+        
+        EdmFunctionImport functionImport3 = container.getFunctionImport("NoParamters");
+        assertEquals("NoParamters", functionImport3.getName());
+        parameterNames = (List<String>) functionImport3.getParameterNames();
+        assertNotNull(parameterNames);
+        assertEquals(0, parameterNames.size());
+
+        EdmFunctionImport functionImport4 = container.getFunctionImport("NoReturn");
+        assertEquals("NoReturn", functionImport4.getName());
+        parameterNames = (List<String>) functionImport4.getParameterNames();
+        assertNotNull(parameterNames);
+        assertEquals(0, parameterNames.size());
+        assertNull(functionImport4.getReturnType());
+
+        EdmFunctionImport functionImport5 = container.getFunctionImport("SingleRoomReturnType");
+        assertEquals("SingleRoomReturnType", functionImport5.getName());
+        parameterNames = (List<String>) functionImport4.getParameterNames();
+        assertNotNull(parameterNames);
+        assertEquals(0, parameterNames.size());
+        assertEquals("Employee",
+            functionImport5.getReturnType().getType().getName());
+        assertEquals(EdmMultiplicity.ONE, functionImport5.getReturnType().getMultiplicity());
+      }
+    }
+  }
+  
+  private InputStream createStreamReader(final String xml) throws 
+  XMLStreamException, UnsupportedEncodingException {
+    return new ByteArrayInputStream(xml.getBytes("UTF-8"));
+  }
+  
+  @Test
+  public void testFunctionImportIn2Containers() throws XMLStreamException, 
+  EntityProviderException, EdmException, UnsupportedEncodingException {
+    final String xmWithEntityContainer =
+        "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\""
+            + Edm.NAMESPACE_EDMX_2007_06
+            + "\">"
+            + "<edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\""
+            + Edm.NAMESPACE_M_2007_08
+            + "\">"
+            + "<Schema Namespace=\""
+            + NAMESPACE
+            + "\" xmlns=\""
+            + Edm.NAMESPACE_EDM_2008_09
+            + "\">"
+            + "<EntityType Name= \"Employee\" m:HasStream=\"true\">"
+            + "<Key><PropertyRef Name=\"EmployeeId\"/></Key>"
+            + "<Property Name=\""
+            + propertyNames[0]
+            + "\" Type=\"Edm.String\" Nullable=\"false\"/>"
+            + "<Property Name=\""
+            + propertyNames[1]
+            + "\" Type=\"Edm.String\" m:FC_TargetPath=\"SyndicationTitle\"/>"
+            + "</EntityType>"
+            + "<EntityContainer Name=\"Container1\" m:IsDefaultEntityContainer=\"true\">"
+            + "<EntitySet Name=\"Employees\" EntityType=\"RefScenario.Employee\"/>"
+            + "<FunctionImport Name=\"EmployeeSearch\" ReturnType=\"Collection(RefScenario.Employee)\" " +
+            "EntitySet=\"Employees\" m:HttpMethod=\"GET\">"
+            + "<Parameter Name=\"q1\" Type=\"Edm.String\" Nullable=\"true\" />"
+            + "<Parameter Name=\"q2\" Type=\"Edm.Int32\" Nullable=\"false\" />"
+            + "</FunctionImport>"
+            + "<FunctionImport Name=\"RoomSearch\" ReturnType=\"Collection(RefScenario.Employee)\" " +
+            "EntitySet=\"Employees\" m:HttpMethod=\"GET\">"
+            + "<Parameter Name=\"q1\" Type=\"Edm.String\" Nullable=\"true\" Mode=\"In\"/>"
+            + "<Parameter Name=\"q2\" Type=\"Edm.Int32\" Nullable=\"false\" />"
+            + "</FunctionImport>"
+            + "</EntityContainer>" 
+            + "<EntityContainer Name=\"Container2\" m:IsDefaultEntityContainer=\"false\">"
+            + "<EntitySet Name=\"Employees\" EntityType=\"RefScenario.Employee\"/>"
+            + "<FunctionImport Name=\"RoomSearch\" ReturnType=\"Collection(RefScenario.Employee)\" " +
+            "EntitySet=\"Employees\" m:HttpMethod=\"GET\">"
+            + "<Parameter Name=\"q1\" Type=\"Edm.String\" Nullable=\"true\" Mode=\"In\"/>"
+            + "<Parameter Name=\"q2\" Type=\"Edm.Int32\" Nullable=\"false\" />"
+            + "</FunctionImport>"
+            + "</EntityContainer>" + 
+            "</Schema>" + "</edmx:DataServices>" + "</edmx:Edmx>";
+    XmlMetadataDeserializer parser = new XmlMetadataDeserializer();
+    InputStream reader = createStreamReader(xmWithEntityContainer);
+    EdmDataServices result = parser.readMetadata(reader, true);
+    for (EdmSchema schema : result.getEdm().getSchemas()) {
+      int i = 0;
+      for (EdmEntityContainer container : schema.getEntityContainers()) {
+        i++;
+        assertEquals("Container" + i, container.getName());
+        EdmFunctionImport functionImport = null;
+        if (container.getName().equals("Container1")) {
+          assertEquals(Boolean.TRUE, container.isDefaultEntityContainer());
+          functionImport = container.getFunctionImport("EmployeeSearch");
+          assertEquals("EmployeeSearch", functionImport.getName());
+          checkParameters1(functionImport);
+          assertEquals(Boolean.TRUE, container.isDefaultEntityContainer());
+          functionImport = container.getFunctionImport("RoomSearch");
+          assertEquals("RoomSearch", functionImport.getName());
+          checkParameters1(functionImport);
+        } else {
+          assertEquals(Boolean.FALSE, container.isDefaultEntityContainer());
+          functionImport = container.getFunctionImport("RoomSearch");
+          assertEquals("RoomSearch", functionImport.getName());
+        }
+        
+      }
+    }
+  }
+
+  /**
+   * @param functionImport
+   * @throws EdmException
+   */
+  private void checkParameters1(EdmFunctionImport functionImport) throws EdmException {
+    assertEquals("Employees", functionImport.getEntitySet().getName());
+    assertEquals("Employee", functionImport.getReturnType().getName());
+    assertEquals(EdmMultiplicity.MANY, functionImport.getReturnType().getMultiplicity());
+    assertEquals(NAMESPACE, functionImport.getReturnType().getType().getNamespace());
+    assertEquals("GET", functionImport.getHttpMethod());
+    List<String> parameterNames = (List<String>) functionImport.getParameterNames();
+    assertEquals(2, parameterNames.size());
+
+    assertEquals("q1", parameterNames.get(0));
+    EdmParameter edmParam = functionImport.getParameter(parameterNames.get(0)); 
+    assertEquals("String", edmParam.getType().getName());
+    assertEquals(Boolean.TRUE, edmParam.getFacets().isNullable());
+
+    assertEquals("q2", parameterNames.get(1));
+    edmParam = functionImport.getParameter(parameterNames.get(1));
+    assertEquals("Int32", edmParam.getType().getName());
+    assertEquals(Boolean.FALSE, edmParam.getFacets().isNullable());
+  }
+  
+  @Test
+  public void testFunctionImportIn2Schemas() throws XMLStreamException,
+  EntityProviderException, EdmException, UnsupportedEncodingException {
+    final String xmWithEntityContainer =
+        "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\""
+            + Edm.NAMESPACE_EDMX_2007_06
+            + "\">"
+            + "<edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\""
+            + Edm.NAMESPACE_M_2007_08
+            + "\">"
+            + "<Schema Namespace=\""
+            + NAMESPACE + "1"
+            + "\" xmlns=\""
+            + Edm.NAMESPACE_EDM_2008_09
+            + "\">"
+            + "<EntityType Name= \"Employee\" m:HasStream=\"true\">"
+            + "<Key><PropertyRef Name=\"EmployeeId\"/></Key>"
+            + "<Property Name=\""
+            + propertyNames[0]
+            + "\" Type=\"Edm.String\" Nullable=\"false\"/>"
+            + "<Property Name=\""
+            + propertyNames[1]
+            + "\" Type=\"Edm.String\" m:FC_TargetPath=\"SyndicationTitle\"/>"
+            + "</EntityType>"
+            + "<EntityContainer Name=\"Container1\" m:IsDefaultEntityContainer=\"true\">"
+            + "<EntitySet Name=\"Employees\" EntityType=\"RefScenario1.Employee\"/>"
+            + "<FunctionImport Name=\"EmployeeSearch\" ReturnType=\"Collection(RefScenario1.Employee)\" " +
+            "EntitySet=\"Employees\" m:HttpMethod=\"GET\">"
+            + "<Parameter Name=\"q1\" Type=\"Edm.String\" Nullable=\"true\" />"
+            + "<Parameter Name=\"q2\" Type=\"Edm.Int32\" Nullable=\"false\" />"
+            + "</FunctionImport>"
+            + "<FunctionImport Name=\"RoomSearch\" ReturnType=\"Collection(RefScenario1.Employee)\" " +
+            "EntitySet=\"Employees\" m:HttpMethod=\"GET\">"
+            + "<Parameter Name=\"q1\" Type=\"Edm.String\" Nullable=\"true\" Mode=\"In\"/>"
+            + "<Parameter Name=\"q2\" Type=\"Edm.Int32\" Nullable=\"false\" />"
+            + "</FunctionImport>"
+            + "</EntityContainer>" 
+            + "<EntityContainer Name=\"Container2\" m:IsDefaultEntityContainer=\"false\">"
+            + "<EntitySet Name=\"Employees\" EntityType=\"RefScenario1.Employee\"/>"
+            + "<FunctionImport Name=\"RoomSearch\" ReturnType=\"Collection(RefScenario1.Employee)\" " +
+            "EntitySet=\"Employees\" m:HttpMethod=\"GET\">"
+            + "<Parameter Name=\"q1\" Type=\"Edm.String\" Nullable=\"true\" Mode=\"In\"/>"
+            + "<Parameter Name=\"q2\" Type=\"Edm.Int32\" Nullable=\"false\" />"
+            + "</FunctionImport>"
+            + "</EntityContainer>" + 
+            "</Schema>" 
+            + "<Schema Namespace=\""
+            + NAMESPACE2
+            + "\" xmlns=\""
+            + Edm.NAMESPACE_EDM_2008_09
+            + "\">"
+            + "<EntityType Name= \"Employee\" m:HasStream=\"true\">"
+            + "<Key><PropertyRef Name=\"EmployeeId\"/></Key>"
+            + "<Property Name=\""
+            + propertyNames[0]
+            + "\" Type=\"Edm.String\" Nullable=\"false\"/>"
+            + "<Property Name=\""
+            + propertyNames[1]
+            + "\" Type=\"Edm.String\" m:FC_TargetPath=\"SyndicationTitle\"/>"
+            + "</EntityType>"
+            + "<EntityContainer Name=\"Container1\" m:IsDefaultEntityContainer=\"true\">"
+            + "<EntitySet Name=\"Employees\" EntityType=\"RefScenario2.Employee\"/>"
+            + "<FunctionImport Name=\"EmployeeSearch\" ReturnType=\"Collection(RefScenario2.Employee)\" " +
+            "EntitySet=\"Employees\" m:HttpMethod=\"GET\">"
+            + "<Parameter Name=\"q1\" Type=\"Edm.String\" Nullable=\"true\" />"
+            + "<Parameter Name=\"q2\" Type=\"Edm.Int32\" Nullable=\"false\" />"
+            + "</FunctionImport>"
+            + "<FunctionImport Name=\"RoomSearch\" ReturnType=\"Collection(RefScenario2.Employee)\" " +
+            "EntitySet=\"Employees\" m:HttpMethod=\"GET\">"
+            + "<Parameter Name=\"q1\" Type=\"Edm.String\" Nullable=\"true\" Mode=\"In\"/>"
+            + "<Parameter Name=\"q2\" Type=\"Edm.Int32\" Nullable=\"false\" />"
+            + "</FunctionImport>"
+            + "</EntityContainer>" 
+            + "</Schema>"
+            + "</edmx:DataServices>" + "</edmx:Edmx>";
+    XmlMetadataDeserializer parser = new XmlMetadataDeserializer();
+    InputStream reader = createStreamReader(xmWithEntityContainer);
+    EdmDataServices result = parser.readMetadata(reader, true);
+    int i = 0;
+    for (EdmSchema schema : result.getEdm().getSchemas()) {
+      i++;
+      assertEquals("RefScenario" + i, schema.getNamespace());
+      int j = 0;
+      for (EdmEntityContainer container : schema.getEntityContainers()) {
+        j++;
+        assertEquals("Container" + j, container.getName());
+        EdmFunctionImport functionImport = null;
+        if (container.getName().equals("Container1") && schema.getNamespace().equalsIgnoreCase("RefScenario" + i)) {
+          assertEquals(Boolean.TRUE, container.isDefaultEntityContainer());
+          functionImport = container.getFunctionImport("EmployeeSearch");
+          assertEquals("EmployeeSearch", functionImport.getName());
+          checkParameters(i, functionImport);
+        } else if (container.getName().equals("Container2") && 
+            schema.getNamespace().equalsIgnoreCase("RefScenario" + i)) {
+          assertEquals(Boolean.FALSE, container.isDefaultEntityContainer());
+          functionImport = container.getFunctionImport("RoomSearch");
+          assertEquals("RoomSearch", functionImport.getName());
+          checkParameters(i, functionImport);
+        }
+      }
+    }
+  }
+
+  /**
+   * @param i
+   * @param functionImport
+   * @throws EdmException
+   */
+  private void checkParameters(int i, EdmFunctionImport functionImport) throws EdmException {
+    assertEquals("Employees", functionImport.getEntitySet().getName());
+    assertEquals("Employee", functionImport.getReturnType().getName());
+    assertEquals(EdmMultiplicity.MANY, functionImport.getReturnType().getMultiplicity());
+    assertEquals(NAMESPACE + i, functionImport.getReturnType().getType().getNamespace());
+    assertEquals("GET", functionImport.getHttpMethod());
+    List<String> parameterNames = (List<String>) functionImport.getParameterNames();
+    assertEquals(2, parameterNames.size());
+
+    assertEquals("q1", parameterNames.get(0));
+    EdmParameter edmParam = functionImport.getParameter(parameterNames.get(0)); 
+    assertEquals("String", edmParam.getType().getName());
+    assertEquals(Boolean.TRUE, edmParam.getFacets().isNullable());
+
+    assertEquals("q2", parameterNames.get(1));
+    edmParam = functionImport.getParameter(parameterNames.get(1));
+    assertEquals("Int32", edmParam.getType().getName());
+    assertEquals(Boolean.FALSE, edmParam.getFacets().isNullable());
+  }
+  
+  @Test(expected = EntityProviderException.class)
+  public void testMissingTypeAtFunctionImport() throws Exception {
+    final String xml =
+        "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\""
+            + Edm.NAMESPACE_EDMX_2007_06
+            + "\">"
+            + "<edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\""
+            + Edm.NAMESPACE_M_2007_08
+            + "\">"
+            + "<Schema Namespace=\""
+            + NAMESPACE
+            + "\" xmlns=\""
+            + Edm.NAMESPACE_EDM_2008_09
+            + "\">"
+            + "<EntityType Name= \"Employee\" m:HasStream=\"true\">"
+            + "<Key><PropertyRef Name=\"EmployeeId\"/></Key>"
+            + "<Property Name=\""
+            + propertyNames[0]
+            + "\" Type=\"Edm.String\" Nullable=\"false\"/>"
+            + "<Property Name=\""
+            + propertyNames[1]
+            + "\" Type=\"Edm.String\" m:FC_TargetPath=\"SyndicationTitle\"/>"
+            + "</EntityType>"
+            + "<EntityContainer Name=\"Container1\" m:IsDefaultEntityContainer=\"true\">"
+            + "<EntitySet Name=\"Employees\" EntityType=\"RefScenario.Employee\"/>"
+            + "<FunctionImport Name=\"EmployeeSearch\" ReturnType=\"Collection(RefScenario.Employee)\" " +
+            "EntitySet=\"Employees\" m:HttpMethod=\"GET\">"
+            + "<Parameter Name=\"q\" Nullable=\"true\" />" + "</FunctionImport>"
+            + "</EntityContainer></Schema></edmx:DataServices></edmx:Edmx>";
+    XmlMetadataDeserializer parser = new XmlMetadataDeserializer();
+    InputStream reader = createStreamReader(xml);
+    try {
+      parser.readMetadata(reader, true);
+    } catch (EntityProviderException e) {
+      assertEquals(EntityProviderException.MISSING_ATTRIBUTE.getKey(), e.getMessageReference().getKey());
+      assertEquals(2, e.getMessageReference().getContent().size());
+      assertEquals("Type", e.getMessageReference().getContent().get(0));
+      assertEquals("Parameter", e.getMessageReference().getContent().get(1));
+      throw e;
+    }
+  }
+  
+  @Test
+  public void testFunctionImportWithAnnotations() throws XMLStreamException, 
+  EntityProviderException, EdmException, UnsupportedEncodingException {
+    final String xmWithEntityContainer =
+        "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\""
+            + Edm.NAMESPACE_EDMX_2007_06 
+            + "\" xmlns:sap=\"http://www.sap.com/Protocols/SAPData\">"
+            + "<edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\""
+            + Edm.NAMESPACE_M_2007_08
+            + "\">"
+            + "<Schema Namespace=\""
+            + NAMESPACE
+            + "\" xmlns=\""
+            + Edm.NAMESPACE_EDM_2008_09
+            + "\">"
+            + "<EntityType Name= \"Employee\" m:HasStream=\"true\">"
+            + "<Key><PropertyRef Name=\"EmployeeId\"/></Key>"
+            + "<Property Name=\""
+            + propertyNames[0]
+            + "\" Type=\"Edm.String\" Nullable=\"false\"/>"
+            + "<Property Name=\""
+            + propertyNames[1]
+            + "\" Type=\"Edm.String\" m:FC_TargetPath=\"SyndicationTitle\"/>"
+            + "</EntityType>"
+            + "<EntityContainer Name=\"Container1\" m:IsDefaultEntityContainer=\"true\">"
+            + "<EntitySet Name=\"Employees\" EntityType=\"RefScenario.Employee\"/>"
+            + "<FunctionImport Name=\"EmployeeSearch\" ReturnType=\"Collection(RefScenario.Employee)\" " 
+            + "EntitySet=\"Employees\" m:HttpMethod=\"GET\" sap:label=\"Approve\" "
+            + "sap:action-for=\"RefScenario.LeaveRequest\" sap:applicable-path=\"ControlData/NeedsApproval\">"
+            + "<Parameter Name=\"q1\" Type=\"Edm.String\" Nullable=\"true\" />"
+            + "<Parameter Name=\"q2\" Type=\"Edm.Int32\" Nullable=\"false\" >"
+            + "<sap:value-constraint set=\"Employees\">"
+            + "<sap:parameter-ref name=\"EmployeeId\" />"
+            + "</sap:value-constraint>"
+            + "</Parameter>"
+            + "</FunctionImport>"
+            + "</EntityContainer>" + "</Schema>" + "</edmx:DataServices>" + "</edmx:Edmx>";
+    XmlMetadataDeserializer parser = new XmlMetadataDeserializer();
+    InputStream reader = createStreamReader(xmWithEntityContainer);
+    EdmDataServices result = parser.readMetadata(reader, true);
+    for (EdmSchema schema : result.getEdm().getSchemas()) {
+      for (EdmEntityContainer container : schema.getEntityContainers()) {
+        assertEquals("Container1", container.getName());
+        assertEquals(Boolean.TRUE, container.isDefaultEntityContainer());
+
+        EdmFunctionImport functionImport1 = container.getFunctionImport("EmployeeSearch");
+
+        assertEquals("EmployeeSearch", functionImport1.getName());
+        checkParametersWithAnnotations(functionImport1);
+      }
+    }
+  }
+  
+  /**
+   * @param functionImport
+   * @throws EdmException
+   */
+  private void checkParametersWithAnnotations(EdmFunctionImport functionImport) throws EdmException {
+    assertEquals("Employees", functionImport.getEntitySet().getName());
+    assertEquals("Employee", functionImport.getReturnType().getName());
+    assertEquals(EdmMultiplicity.MANY, functionImport.getReturnType().getMultiplicity());
+    assertEquals(NAMESPACE, functionImport.getReturnType().getType().getNamespace());
+    assertEquals("GET", functionImport.getHttpMethod());
+    List<EdmAnnotationAttribute> annotationAttrs = functionImport.getAnnotations().getAnnotationAttributes();
+    assertEquals(3, annotationAttrs.size());
+    assertEquals("label", annotationAttrs.get(0).getName());
+    assertEquals("Approve", annotationAttrs.get(0).getText());
+    assertEquals("sap", annotationAttrs.get(0).getPrefix());
+    assertEquals("http://www.sap.com/Protocols/SAPData", annotationAttrs.get(0).getNamespace());
+    assertEquals("action-for", annotationAttrs.get(1).getName());
+    assertEquals("RefScenario.LeaveRequest", annotationAttrs.get(1).getText());
+    assertEquals("sap", annotationAttrs.get(1).getPrefix());
+    assertEquals("http://www.sap.com/Protocols/SAPData", annotationAttrs.get(1).getNamespace());
+    assertEquals("applicable-path", annotationAttrs.get(2).getName());
+    assertEquals("ControlData/NeedsApproval", annotationAttrs.get(2).getText());
+    assertEquals("sap", annotationAttrs.get(2).getPrefix());
+    assertEquals("http://www.sap.com/Protocols/SAPData", annotationAttrs.get(2).getNamespace());
+      
+    List<String> parameterNames = (List<String>) functionImport.getParameterNames();
+    assertEquals(2, parameterNames.size());
+
+    assertEquals("q1", parameterNames.get(0));
+    EdmParameter edmParam = functionImport.getParameter(parameterNames.get(0)); 
+    assertEquals("String", edmParam.getType().getName());
+    assertEquals(Boolean.TRUE, edmParam.getFacets().isNullable());
+
+    assertEquals("q2", parameterNames.get(1));
+    edmParam = functionImport.getParameter(parameterNames.get(1));
+    EdmAnnotations edmParamAnnotations = edmParam.getAnnotations();
+    if (edmParamAnnotations != null) {
+      for (EdmAnnotationElement annotationEle : edmParamAnnotations.getAnnotationElements()) {
+        assertEquals("value-constraint", annotationEle.getName());
+        assertEquals("http://www.sap.com/Protocols/SAPData", annotationEle.getNamespace());
+        assertEquals("sap", annotationEle.getPrefix());
+        for (EdmAnnotationAttribute annotationAttr : annotationEle.getAttributes()) {
+          assertEquals("set", annotationAttr.getName());
+          assertEquals("Employees", annotationAttr.getText());
+        }
+        for (EdmAnnotationElement childAnnotationEle : annotationEle.getChildElements()) {
+          assertEquals("parameter-ref", childAnnotationEle.getName());
+          assertEquals("http://www.sap.com/Protocols/SAPData", childAnnotationEle.getNamespace());
+          assertEquals("sap", childAnnotationEle.getPrefix());
+          for (EdmAnnotationAttribute childAnnotationAttr : childAnnotationEle.getAttributes()) {
+            assertEquals("name", childAnnotationAttr.getName());
+            assertEquals("EmployeeId", childAnnotationAttr.getText());
+          }
+        }
+      }
+    }
+    assertEquals("Int32", edmParam.getType().getName());
+    assertEquals(Boolean.FALSE, edmParam.getFacets().isNullable());
+  }
+  
+  @Test
+  public void testSameFunctionImportIn2Containers() throws XMLStreamException, 
+  EntityProviderException, EdmException, UnsupportedEncodingException {
+    final String xmWithEntityContainer =
+        "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\""
+            + Edm.NAMESPACE_EDMX_2007_06
+            + "\">"
+            + "<edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\""
+            + Edm.NAMESPACE_M_2007_08
+            + "\">"
+            + "<Schema Namespace=\""
+            + NAMESPACE
+            + "\" xmlns=\""
+            + Edm.NAMESPACE_EDM_2008_09
+            + "\">"
+            + "<EntityType Name= \"Employee\" m:HasStream=\"true\">"
+            + "<Key><PropertyRef Name=\"EmployeeId\"/></Key>"
+            + "<Property Name=\""
+            + propertyNames[0]
+            + "\" Type=\"Edm.String\" Nullable=\"false\"/>"
+            + "<Property Name=\""
+            + propertyNames[1]
+            + "\" Type=\"Edm.String\" m:FC_TargetPath=\"SyndicationTitle\"/>"
+            + "</EntityType>"
+            + "<EntityContainer Name=\"Container1\" m:IsDefaultEntityContainer=\"true\">"
+            + "<EntitySet Name=\"Employees\" EntityType=\"RefScenario.Employee\"/>"
+            + "<FunctionImport Name=\"EmployeeSearch\" ReturnType=\"Collection(RefScenario.Employee)\" " +
+            "EntitySet=\"Employees\" m:HttpMethod=\"GET\">"
+            + "<Parameter Name=\"q1\" Type=\"Edm.String\" Nullable=\"true\" />"
+            + "<Parameter Name=\"q2\" Type=\"Edm.Int32\" Nullable=\"false\" />"
+            + "</FunctionImport>"
+            + "</EntityContainer>" + "<EntityContainer Name=\"Container2\" m:IsDefaultEntityContainer=\"false\">"
+            + "<EntitySet Name=\"Employees\" EntityType=\"RefScenario.Employee\"/>"
+            + "<FunctionImport Name=\"EmployeeSearch\" ReturnType=\"Collection(RefScenario.Employee)\" " +
+            "EntitySet=\"Employees\" m:HttpMethod=\"GET\">"
+            + "<Parameter Name=\"q1\" Type=\"Edm.String\" Nullable=\"true\" />"
+            + "<Parameter Name=\"q2\" Type=\"Edm.Int32\" Nullable=\"false\" />"
+            + "</FunctionImport>"
+            + "</EntityContainer>" 
+            + "</Schema>" + "</edmx:DataServices>" + "</edmx:Edmx>";
+    XmlMetadataDeserializer parser = new XmlMetadataDeserializer();
+    InputStream reader = createStreamReader(xmWithEntityContainer);
+    EdmDataServices result = parser.readMetadata(reader, true);
+    for (EdmSchema schema : result.getEdm().getSchemas()) {
+      for (EdmEntityContainer container : schema.getEntityContainers()) {
+        if (container.getName().equalsIgnoreCase("Container1")) {
+          assertEquals(Boolean.TRUE, container.isDefaultEntityContainer());
+          EdmFunctionImport functionImport1 = container.getFunctionImport("EmployeeSearch");
+          assertEquals("EmployeeSearch", functionImport1.getName());
+          checkParameters1(functionImport1);
+        } else if (container.getName().equalsIgnoreCase("Container2")) {
+          assertEquals(Boolean.FALSE, container.isDefaultEntityContainer());
+          EdmFunctionImport functionImport1 = container.getFunctionImport("EmployeeSearch");
+          assertEquals("EmployeeSearch", functionImport1.getName());
+          checkParameters1(functionImport1);
+        }
+      }
+    }
+  }
+}


[03/24] olingo-odata2 git commit: [OLINGO-1253]Client Module for Olingo v2

Posted by ar...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/resources/LargeEmployeeFeed.xml
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/resources/LargeEmployeeFeed.xml b/odata2-lib/odata-client-core/src/test/resources/LargeEmployeeFeed.xml
new file mode 100644
index 0000000..e9b58d9
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/resources/LargeEmployeeFeed.xml
@@ -0,0 +1,12556 @@
+<?xml version='1.0' encoding='utf-8'?>
+<!--
+ 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.
+ -->
+<feed 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="https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/">
+	<id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees</id>
+	<title type="text">Employees</title>
+	<updated>2013-12-02T12:20:28.605Z</updated>
+	<author>
+		<name/>
+	</author>
+	<link href="Employees" rel="self" title="Employees"/>
+	<entry>
+		<id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/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="image/jpeg"/>
+		<link href="Employees('1')/ne_Manager" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager" title="ne_Manager" type="application/atom+xml;type=entry"/>
+		<link href="Employees('1')/ne_Team" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team" title="ne_Team" type="application/atom+xml;type=entry"/>
+		<link href="Employees('1')/ne_Room" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room" title="ne_Room" type="application/atom+xml;type=entry"/>
+		<content type="image/jpeg" 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:City m:type="RefScenario.c_City">
+					<d:PostalCode>69124</d:PostalCode>
+					<d:CityName>Heidelberg</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>52</d:Age>
+			<d:EntryDate>1999-01-01T00:00:00</d:EntryDate>
+			<d:ImageUrl>Employees('1')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+	<entry>
+		<id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('2')</id>
+		<title type="text">Frederic Fall</title>
+		<updated>2003-07-01T00:00:00Z</updated>
+		<category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+		<link href="Employees('2')" rel="edit" title="Employee"/>
+		<link href="Employees('2')/$value" rel="edit-media" type="image/jpeg"/>
+		<link href="Employees('2')/ne_Manager" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager" title="ne_Manager" type="application/atom+xml;type=entry"/>
+		<link href="Employees('2')/ne_Team" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team" title="ne_Team" type="application/atom+xml;type=entry"/>
+		<link href="Employees('2')/ne_Room" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room" title="ne_Room" type="application/atom+xml;type=entry"/>
+		<content type="image/jpeg" src="Employees('2')/$value"/>
+		<m:properties>
+			<d:EmployeeId>2</d:EmployeeId>
+			<d:EmployeeName>Frederic Fall</d:EmployeeName>
+			<d:ManagerId>1</d:ManagerId>
+			<d:RoomId>2</d:RoomId>
+			<d:TeamId>1</d:TeamId>
+			<d:Location m:type="RefScenario.c_Location">
+				<d:City m:type="RefScenario.c_City">
+					<d:PostalCode>69190</d:PostalCode>
+					<d:CityName>Walldorf</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>32</d:Age>
+			<d:EntryDate>2003-07-01T00:00:00</d:EntryDate>
+			<d:ImageUrl>Employees('2')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+	<entry>
+		<id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('3')</id>
+		<title type="text">Jonathan Smith</title>
+		<updated>2013-12-02T12:20:28.622Z</updated>
+		<category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+		<link href="Employees('3')" rel="edit" title="Employee"/>
+		<link href="Employees('3')/$value" rel="edit-media" type="image/jpeg"/>
+		<link href="Employees('3')/ne_Manager" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager" title="ne_Manager" type="application/atom+xml;type=entry"/>
+		<link href="Employees('3')/ne_Team" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team" title="ne_Team" type="application/atom+xml;type=entry"/>
+		<link href="Employees('3')/ne_Room" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room" title="ne_Room" type="application/atom+xml;type=entry"/>
+		<content type="image/jpeg" src="Employees('3')/$value"/>
+		<m:properties>
+			<d:EmployeeId>3</d:EmployeeId>
+			<d:EmployeeName>Jonathan Smith</d:EmployeeName>
+			<d:ManagerId>1</d:ManagerId>
+			<d:RoomId>2</d:RoomId>
+			<d:TeamId>1</d:TeamId>
+			<d:Location m:type="RefScenario.c_Location">
+				<d:City m:type="RefScenario.c_City">
+					<d:PostalCode>69190</d:PostalCode>
+					<d:CityName>Walldorf</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>56</d:Age>
+			<d:EntryDate m:null="true"/>
+			<d:ImageUrl>Employees('3')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+	<entry>
+		<id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('4')</id>
+		<title type="text">Peter Burke</title>
+		<updated>2004-09-12T00:00:00Z</updated>
+		<category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+		<link href="Employees('4')" rel="edit" title="Employee"/>
+		<link href="Employees('4')/$value" rel="edit-media" type="image/jpeg"/>
+		<link href="Employees('4')/ne_Manager" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager" title="ne_Manager" type="application/atom+xml;type=entry"/>
+		<link href="Employees('4')/ne_Team" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team" title="ne_Team" type="application/atom+xml;type=entry"/>
+		<link href="Employees('4')/ne_Room" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room" title="ne_Room" type="application/atom+xml;type=entry"/>
+		<content type="image/jpeg" src="Employees('4')/$value"/>
+		<m:properties>
+			<d:EmployeeId>4</d:EmployeeId>
+			<d:EmployeeName>Peter Burke</d:EmployeeName>
+			<d:ManagerId>3</d:ManagerId>
+			<d:RoomId>2</d:RoomId>
+			<d:TeamId>2</d:TeamId>
+			<d:Location m:type="RefScenario.c_Location">
+				<d:City m:type="RefScenario.c_City">
+					<d:PostalCode>69190</d:PostalCode>
+					<d:CityName>Walldorf</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>39</d:Age>
+			<d:EntryDate>2004-09-12T00:00:00</d:EntryDate>
+			<d:ImageUrl>Employees('4')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+	<entry>
+		<id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('5')</id>
+		<title type="text">John Field</title>
+		<updated>2001-02-01T00:00:00Z</updated>
+		<category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+		<link href="Employees('5')" rel="edit" title="Employee"/>
+		<link href="Employees('5')/$value" rel="edit-media" type="image/jpeg"/>
+		<link href="Employees('5')/ne_Manager" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager" title="ne_Manager" type="application/atom+xml;type=entry"/>
+		<link href="Employees('5')/ne_Team" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team" title="ne_Team" type="application/atom+xml;type=entry"/>
+		<link href="Employees('5')/ne_Room" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room" title="ne_Room" type="application/atom+xml;type=entry"/>
+		<content type="image/jpeg" src="Employees('5')/$value"/>
+		<m:properties>
+			<d:EmployeeId>5</d:EmployeeId>
+			<d:EmployeeName>John Field</d:EmployeeName>
+			<d:ManagerId>3</d:ManagerId>
+			<d:RoomId>3</d:RoomId>
+			<d:TeamId>2</d:TeamId>
+			<d:Location m:type="RefScenario.c_Location">
+				<d:City m:type="RefScenario.c_City">
+					<d:PostalCode>69190</d:PostalCode>
+					<d:CityName>Walldorf</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>42</d:Age>
+			<d:EntryDate>2001-02-01T00:00:00</d:EntryDate>
+			<d:ImageUrl>Employees('5')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+	<entry>
+		<id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('6')</id>
+		<title type="text">Susan Bay</title>
+		<updated>2010-12-01T00:00:00Z</updated>
+		<category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+		<link href="Employees('6')" rel="edit" title="Employee"/>
+		<link href="Employees('6')/$value" rel="edit-media" type="image/jpeg"/>
+		<link href="Employees('6')/ne_Manager" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager" title="ne_Manager" type="application/atom+xml;type=entry"/>
+		<link href="Employees('6')/ne_Team" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team" title="ne_Team" type="application/atom+xml;type=entry"/>
+		<link href="Employees('6')/ne_Room" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room" title="ne_Room" type="application/atom+xml;type=entry"/>
+		<content type="image/jpeg" src="Employees('6')/$value"/>
+		<m:properties>
+			<d:EmployeeId>6</d:EmployeeId>
+			<d:EmployeeName>Susan Bay</d:EmployeeName>
+			<d:ManagerId>1</d:ManagerId>
+			<d:RoomId>2</d:RoomId>
+			<d:TeamId>3</d:TeamId>
+			<d:Location m:type="RefScenario.c_Location">
+				<d:City m:type="RefScenario.c_City">
+					<d:PostalCode>69190</d:PostalCode>
+					<d:CityName>Walldorf</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>29</d:Age>
+			<d:EntryDate>2010-12-01T00:00:00</d:EntryDate>
+			<d:ImageUrl>Employees('6')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+	<entry>
+		<id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/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="image/jpeg"/>
+		<link href="Employees('1')/ne_Manager" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager" title="ne_Manager" type="application/atom+xml;type=entry"/>
+		<link href="Employees('1')/ne_Team" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team" title="ne_Team" type="application/atom+xml;type=entry"/>
+		<link href="Employees('1')/ne_Room" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room" title="ne_Room" type="application/atom+xml;type=entry"/>
+		<content type="image/jpeg" 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:City m:type="RefScenario.c_City">
+					<d:PostalCode>69124</d:PostalCode>
+					<d:CityName>Heidelberg</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>52</d:Age>
+			<d:EntryDate>1999-01-01T00:00:00</d:EntryDate>
+			<d:ImageUrl>Employees('1')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+	<entry>
+		<id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('2')</id>
+		<title type="text">Frederic Fall</title>
+		<updated>2003-07-01T00:00:00Z</updated>
+		<category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+		<link href="Employees('2')" rel="edit" title="Employee"/>
+		<link href="Employees('2')/$value" rel="edit-media" type="image/jpeg"/>
+		<link href="Employees('2')/ne_Manager" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager" title="ne_Manager" type="application/atom+xml;type=entry"/>
+		<link href="Employees('2')/ne_Team" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team" title="ne_Team" type="application/atom+xml;type=entry"/>
+		<link href="Employees('2')/ne_Room" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room" title="ne_Room" type="application/atom+xml;type=entry"/>
+		<content type="image/jpeg" src="Employees('2')/$value"/>
+		<m:properties>
+			<d:EmployeeId>2</d:EmployeeId>
+			<d:EmployeeName>Frederic Fall</d:EmployeeName>
+			<d:ManagerId>1</d:ManagerId>
+			<d:RoomId>2</d:RoomId>
+			<d:TeamId>1</d:TeamId>
+			<d:Location m:type="RefScenario.c_Location">
+				<d:City m:type="RefScenario.c_City">
+					<d:PostalCode>69190</d:PostalCode>
+					<d:CityName>Walldorf</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>32</d:Age>
+			<d:EntryDate>2003-07-01T00:00:00</d:EntryDate>
+			<d:ImageUrl>Employees('2')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+	<entry>
+		<id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('3')</id>
+		<title type="text">Jonathan Smith</title>
+		<updated>2013-12-02T12:20:28.622Z</updated>
+		<category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+		<link href="Employees('3')" rel="edit" title="Employee"/>
+		<link href="Employees('3')/$value" rel="edit-media" type="image/jpeg"/>
+		<link href="Employees('3')/ne_Manager" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager" title="ne_Manager" type="application/atom+xml;type=entry"/>
+		<link href="Employees('3')/ne_Team" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team" title="ne_Team" type="application/atom+xml;type=entry"/>
+		<link href="Employees('3')/ne_Room" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room" title="ne_Room" type="application/atom+xml;type=entry"/>
+		<content type="image/jpeg" src="Employees('3')/$value"/>
+		<m:properties>
+			<d:EmployeeId>3</d:EmployeeId>
+			<d:EmployeeName>Jonathan Smith</d:EmployeeName>
+			<d:ManagerId>1</d:ManagerId>
+			<d:RoomId>2</d:RoomId>
+			<d:TeamId>1</d:TeamId>
+			<d:Location m:type="RefScenario.c_Location">
+				<d:City m:type="RefScenario.c_City">
+					<d:PostalCode>69190</d:PostalCode>
+					<d:CityName>Walldorf</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>56</d:Age>
+			<d:EntryDate m:null="true"/>
+			<d:ImageUrl>Employees('3')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+	<entry>
+		<id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('4')</id>
+		<title type="text">Peter Burke</title>
+		<updated>2004-09-12T00:00:00Z</updated>
+		<category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+		<link href="Employees('4')" rel="edit" title="Employee"/>
+		<link href="Employees('4')/$value" rel="edit-media" type="image/jpeg"/>
+		<link href="Employees('4')/ne_Manager" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager" title="ne_Manager" type="application/atom+xml;type=entry"/>
+		<link href="Employees('4')/ne_Team" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team" title="ne_Team" type="application/atom+xml;type=entry"/>
+		<link href="Employees('4')/ne_Room" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room" title="ne_Room" type="application/atom+xml;type=entry"/>
+		<content type="image/jpeg" src="Employees('4')/$value"/>
+		<m:properties>
+			<d:EmployeeId>4</d:EmployeeId>
+			<d:EmployeeName>Peter Burke</d:EmployeeName>
+			<d:ManagerId>3</d:ManagerId>
+			<d:RoomId>2</d:RoomId>
+			<d:TeamId>2</d:TeamId>
+			<d:Location m:type="RefScenario.c_Location">
+				<d:City m:type="RefScenario.c_City">
+					<d:PostalCode>69190</d:PostalCode>
+					<d:CityName>Walldorf</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>39</d:Age>
+			<d:EntryDate>2004-09-12T00:00:00</d:EntryDate>
+			<d:ImageUrl>Employees('4')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+	<entry>
+		<id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('5')</id>
+		<title type="text">John Field</title>
+		<updated>2001-02-01T00:00:00Z</updated>
+		<category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+		<link href="Employees('5')" rel="edit" title="Employee"/>
+		<link href="Employees('5')/$value" rel="edit-media" type="image/jpeg"/>
+		<link href="Employees('5')/ne_Manager" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager" title="ne_Manager" type="application/atom+xml;type=entry"/>
+		<link href="Employees('5')/ne_Team" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team" title="ne_Team" type="application/atom+xml;type=entry"/>
+		<link href="Employees('5')/ne_Room" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room" title="ne_Room" type="application/atom+xml;type=entry"/>
+		<content type="image/jpeg" src="Employees('5')/$value"/>
+		<m:properties>
+			<d:EmployeeId>5</d:EmployeeId>
+			<d:EmployeeName>John Field</d:EmployeeName>
+			<d:ManagerId>3</d:ManagerId>
+			<d:RoomId>3</d:RoomId>
+			<d:TeamId>2</d:TeamId>
+			<d:Location m:type="RefScenario.c_Location">
+				<d:City m:type="RefScenario.c_City">
+					<d:PostalCode>69190</d:PostalCode>
+					<d:CityName>Walldorf</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>42</d:Age>
+			<d:EntryDate>2001-02-01T00:00:00</d:EntryDate>
+			<d:ImageUrl>Employees('5')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+	<entry>
+		<id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('6')</id>
+		<title type="text">Susan Bay</title>
+		<updated>2010-12-01T00:00:00Z</updated>
+		<category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+		<link href="Employees('6')" rel="edit" title="Employee"/>
+		<link href="Employees('6')/$value" rel="edit-media" type="image/jpeg"/>
+		<link href="Employees('6')/ne_Manager" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager" title="ne_Manager" type="application/atom+xml;type=entry"/>
+		<link href="Employees('6')/ne_Team" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team" title="ne_Team" type="application/atom+xml;type=entry"/>
+		<link href="Employees('6')/ne_Room" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room" title="ne_Room" type="application/atom+xml;type=entry"/>
+		<content type="image/jpeg" src="Employees('6')/$value"/>
+		<m:properties>
+			<d:EmployeeId>6</d:EmployeeId>
+			<d:EmployeeName>Susan Bay</d:EmployeeName>
+			<d:ManagerId>1</d:ManagerId>
+			<d:RoomId>2</d:RoomId>
+			<d:TeamId>3</d:TeamId>
+			<d:Location m:type="RefScenario.c_Location">
+				<d:City m:type="RefScenario.c_City">
+					<d:PostalCode>69190</d:PostalCode>
+					<d:CityName>Walldorf</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>29</d:Age>
+			<d:EntryDate>2010-12-01T00:00:00</d:EntryDate>
+			<d:ImageUrl>Employees('6')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+	<entry>
+		<id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/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="image/jpeg"/>
+		<link href="Employees('1')/ne_Manager" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager" title="ne_Manager" type="application/atom+xml;type=entry"/>
+		<link href="Employees('1')/ne_Team" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team" title="ne_Team" type="application/atom+xml;type=entry"/>
+		<link href="Employees('1')/ne_Room" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room" title="ne_Room" type="application/atom+xml;type=entry"/>
+		<content type="image/jpeg" 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:City m:type="RefScenario.c_City">
+					<d:PostalCode>69124</d:PostalCode>
+					<d:CityName>Heidelberg</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>52</d:Age>
+			<d:EntryDate>1999-01-01T00:00:00</d:EntryDate>
+			<d:ImageUrl>Employees('1')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+	<entry>
+		<id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('2')</id>
+		<title type="text">Frederic Fall</title>
+		<updated>2003-07-01T00:00:00Z</updated>
+		<category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+		<link href="Employees('2')" rel="edit" title="Employee"/>
+		<link href="Employees('2')/$value" rel="edit-media" type="image/jpeg"/>
+		<link href="Employees('2')/ne_Manager" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager" title="ne_Manager" type="application/atom+xml;type=entry"/>
+		<link href="Employees('2')/ne_Team" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team" title="ne_Team" type="application/atom+xml;type=entry"/>
+		<link href="Employees('2')/ne_Room" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room" title="ne_Room" type="application/atom+xml;type=entry"/>
+		<content type="image/jpeg" src="Employees('2')/$value"/>
+		<m:properties>
+			<d:EmployeeId>2</d:EmployeeId>
+			<d:EmployeeName>Frederic Fall</d:EmployeeName>
+			<d:ManagerId>1</d:ManagerId>
+			<d:RoomId>2</d:RoomId>
+			<d:TeamId>1</d:TeamId>
+			<d:Location m:type="RefScenario.c_Location">
+				<d:City m:type="RefScenario.c_City">
+					<d:PostalCode>69190</d:PostalCode>
+					<d:CityName>Walldorf</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>32</d:Age>
+			<d:EntryDate>2003-07-01T00:00:00</d:EntryDate>
+			<d:ImageUrl>Employees('2')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+	<entry>
+		<id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('3')</id>
+		<title type="text">Jonathan Smith</title>
+		<updated>2013-12-02T12:20:28.622Z</updated>
+		<category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+		<link href="Employees('3')" rel="edit" title="Employee"/>
+		<link href="Employees('3')/$value" rel="edit-media" type="image/jpeg"/>
+		<link href="Employees('3')/ne_Manager" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager" title="ne_Manager" type="application/atom+xml;type=entry"/>
+		<link href="Employees('3')/ne_Team" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team" title="ne_Team" type="application/atom+xml;type=entry"/>
+		<link href="Employees('3')/ne_Room" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room" title="ne_Room" type="application/atom+xml;type=entry"/>
+		<content type="image/jpeg" src="Employees('3')/$value"/>
+		<m:properties>
+			<d:EmployeeId>3</d:EmployeeId>
+			<d:EmployeeName>Jonathan Smith</d:EmployeeName>
+			<d:ManagerId>1</d:ManagerId>
+			<d:RoomId>2</d:RoomId>
+			<d:TeamId>1</d:TeamId>
+			<d:Location m:type="RefScenario.c_Location">
+				<d:City m:type="RefScenario.c_City">
+					<d:PostalCode>69190</d:PostalCode>
+					<d:CityName>Walldorf</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>56</d:Age>
+			<d:EntryDate m:null="true"/>
+			<d:ImageUrl>Employees('3')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+	<entry>
+		<id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('4')</id>
+		<title type="text">Peter Burke</title>
+		<updated>2004-09-12T00:00:00Z</updated>
+		<category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+		<link href="Employees('4')" rel="edit" title="Employee"/>
+		<link href="Employees('4')/$value" rel="edit-media" type="image/jpeg"/>
+		<link href="Employees('4')/ne_Manager" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager" title="ne_Manager" type="application/atom+xml;type=entry"/>
+		<link href="Employees('4')/ne_Team" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team" title="ne_Team" type="application/atom+xml;type=entry"/>
+		<link href="Employees('4')/ne_Room" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room" title="ne_Room" type="application/atom+xml;type=entry"/>
+		<content type="image/jpeg" src="Employees('4')/$value"/>
+		<m:properties>
+			<d:EmployeeId>4</d:EmployeeId>
+			<d:EmployeeName>Peter Burke</d:EmployeeName>
+			<d:ManagerId>3</d:ManagerId>
+			<d:RoomId>2</d:RoomId>
+			<d:TeamId>2</d:TeamId>
+			<d:Location m:type="RefScenario.c_Location">
+				<d:City m:type="RefScenario.c_City">
+					<d:PostalCode>69190</d:PostalCode>
+					<d:CityName>Walldorf</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>39</d:Age>
+			<d:EntryDate>2004-09-12T00:00:00</d:EntryDate>
+			<d:ImageUrl>Employees('4')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+	<entry>
+		<id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('5')</id>
+		<title type="text">John Field</title>
+		<updated>2001-02-01T00:00:00Z</updated>
+		<category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+		<link href="Employees('5')" rel="edit" title="Employee"/>
+		<link href="Employees('5')/$value" rel="edit-media" type="image/jpeg"/>
+		<link href="Employees('5')/ne_Manager" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager" title="ne_Manager" type="application/atom+xml;type=entry"/>
+		<link href="Employees('5')/ne_Team" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team" title="ne_Team" type="application/atom+xml;type=entry"/>
+		<link href="Employees('5')/ne_Room" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room" title="ne_Room" type="application/atom+xml;type=entry"/>
+		<content type="image/jpeg" src="Employees('5')/$value"/>
+		<m:properties>
+			<d:EmployeeId>5</d:EmployeeId>
+			<d:EmployeeName>John Field</d:EmployeeName>
+			<d:ManagerId>3</d:ManagerId>
+			<d:RoomId>3</d:RoomId>
+			<d:TeamId>2</d:TeamId>
+			<d:Location m:type="RefScenario.c_Location">
+				<d:City m:type="RefScenario.c_City">
+					<d:PostalCode>69190</d:PostalCode>
+					<d:CityName>Walldorf</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>42</d:Age>
+			<d:EntryDate>2001-02-01T00:00:00</d:EntryDate>
+			<d:ImageUrl>Employees('5')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+	<entry>
+		<id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('6')</id>
+		<title type="text">Susan Bay</title>
+		<updated>2010-12-01T00:00:00Z</updated>
+		<category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+		<link href="Employees('6')" rel="edit" title="Employee"/>
+		<link href="Employees('6')/$value" rel="edit-media" type="image/jpeg"/>
+		<link href="Employees('6')/ne_Manager" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager" title="ne_Manager" type="application/atom+xml;type=entry"/>
+		<link href="Employees('6')/ne_Team" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team" title="ne_Team" type="application/atom+xml;type=entry"/>
+		<link href="Employees('6')/ne_Room" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room" title="ne_Room" type="application/atom+xml;type=entry"/>
+		<content type="image/jpeg" src="Employees('6')/$value"/>
+		<m:properties>
+			<d:EmployeeId>6</d:EmployeeId>
+			<d:EmployeeName>Susan Bay</d:EmployeeName>
+			<d:ManagerId>1</d:ManagerId>
+			<d:RoomId>2</d:RoomId>
+			<d:TeamId>3</d:TeamId>
+			<d:Location m:type="RefScenario.c_Location">
+				<d:City m:type="RefScenario.c_City">
+					<d:PostalCode>69190</d:PostalCode>
+					<d:CityName>Walldorf</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>29</d:Age>
+			<d:EntryDate>2010-12-01T00:00:00</d:EntryDate>
+			<d:ImageUrl>Employees('6')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+	<entry>
+		<id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/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="image/jpeg"/>
+		<link href="Employees('1')/ne_Manager" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager" title="ne_Manager" type="application/atom+xml;type=entry"/>
+		<link href="Employees('1')/ne_Team" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team" title="ne_Team" type="application/atom+xml;type=entry"/>
+		<link href="Employees('1')/ne_Room" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room" title="ne_Room" type="application/atom+xml;type=entry"/>
+		<content type="image/jpeg" 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:City m:type="RefScenario.c_City">
+					<d:PostalCode>69124</d:PostalCode>
+					<d:CityName>Heidelberg</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>52</d:Age>
+			<d:EntryDate>1999-01-01T00:00:00</d:EntryDate>
+			<d:ImageUrl>Employees('1')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+	<entry>
+		<id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('2')</id>
+		<title type="text">Frederic Fall</title>
+		<updated>2003-07-01T00:00:00Z</updated>
+		<category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+		<link href="Employees('2')" rel="edit" title="Employee"/>
+		<link href="Employees('2')/$value" rel="edit-media" type="image/jpeg"/>
+		<link href="Employees('2')/ne_Manager" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager" title="ne_Manager" type="application/atom+xml;type=entry"/>
+		<link href="Employees('2')/ne_Team" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team" title="ne_Team" type="application/atom+xml;type=entry"/>
+		<link href="Employees('2')/ne_Room" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room" title="ne_Room" type="application/atom+xml;type=entry"/>
+		<content type="image/jpeg" src="Employees('2')/$value"/>
+		<m:properties>
+			<d:EmployeeId>2</d:EmployeeId>
+			<d:EmployeeName>Frederic Fall</d:EmployeeName>
+			<d:ManagerId>1</d:ManagerId>
+			<d:RoomId>2</d:RoomId>
+			<d:TeamId>1</d:TeamId>
+			<d:Location m:type="RefScenario.c_Location">
+				<d:City m:type="RefScenario.c_City">
+					<d:PostalCode>69190</d:PostalCode>
+					<d:CityName>Walldorf</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>32</d:Age>
+			<d:EntryDate>2003-07-01T00:00:00</d:EntryDate>
+			<d:ImageUrl>Employees('2')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+	<entry>
+		<id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('3')</id>
+		<title type="text">Jonathan Smith</title>
+		<updated>2013-12-02T12:20:28.622Z</updated>
+		<category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+		<link href="Employees('3')" rel="edit" title="Employee"/>
+		<link href="Employees('3')/$value" rel="edit-media" type="image/jpeg"/>
+		<link href="Employees('3')/ne_Manager" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager" title="ne_Manager" type="application/atom+xml;type=entry"/>
+		<link href="Employees('3')/ne_Team" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team" title="ne_Team" type="application/atom+xml;type=entry"/>
+		<link href="Employees('3')/ne_Room" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room" title="ne_Room" type="application/atom+xml;type=entry"/>
+		<content type="image/jpeg" src="Employees('3')/$value"/>
+		<m:properties>
+			<d:EmployeeId>3</d:EmployeeId>
+			<d:EmployeeName>Jonathan Smith</d:EmployeeName>
+			<d:ManagerId>1</d:ManagerId>
+			<d:RoomId>2</d:RoomId>
+			<d:TeamId>1</d:TeamId>
+			<d:Location m:type="RefScenario.c_Location">
+				<d:City m:type="RefScenario.c_City">
+					<d:PostalCode>69190</d:PostalCode>
+					<d:CityName>Walldorf</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>56</d:Age>
+			<d:EntryDate m:null="true"/>
+			<d:ImageUrl>Employees('3')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+	<entry>
+		<id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('4')</id>
+		<title type="text">Peter Burke</title>
+		<updated>2004-09-12T00:00:00Z</updated>
+		<category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+		<link href="Employees('4')" rel="edit" title="Employee"/>
+		<link href="Employees('4')/$value" rel="edit-media" type="image/jpeg"/>
+		<link href="Employees('4')/ne_Manager" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager" title="ne_Manager" type="application/atom+xml;type=entry"/>
+		<link href="Employees('4')/ne_Team" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team" title="ne_Team" type="application/atom+xml;type=entry"/>
+		<link href="Employees('4')/ne_Room" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room" title="ne_Room" type="application/atom+xml;type=entry"/>
+		<content type="image/jpeg" src="Employees('4')/$value"/>
+		<m:properties>
+			<d:EmployeeId>4</d:EmployeeId>
+			<d:EmployeeName>Peter Burke</d:EmployeeName>
+			<d:ManagerId>3</d:ManagerId>
+			<d:RoomId>2</d:RoomId>
+			<d:TeamId>2</d:TeamId>
+			<d:Location m:type="RefScenario.c_Location">
+				<d:City m:type="RefScenario.c_City">
+					<d:PostalCode>69190</d:PostalCode>
+					<d:CityName>Walldorf</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>39</d:Age>
+			<d:EntryDate>2004-09-12T00:00:00</d:EntryDate>
+			<d:ImageUrl>Employees('4')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+	<entry>
+		<id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('5')</id>
+		<title type="text">John Field</title>
+		<updated>2001-02-01T00:00:00Z</updated>
+		<category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+		<link href="Employees('5')" rel="edit" title="Employee"/>
+		<link href="Employees('5')/$value" rel="edit-media" type="image/jpeg"/>
+		<link href="Employees('5')/ne_Manager" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager" title="ne_Manager" type="application/atom+xml;type=entry"/>
+		<link href="Employees('5')/ne_Team" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team" title="ne_Team" type="application/atom+xml;type=entry"/>
+		<link href="Employees('5')/ne_Room" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room" title="ne_Room" type="application/atom+xml;type=entry"/>
+		<content type="image/jpeg" src="Employees('5')/$value"/>
+		<m:properties>
+			<d:EmployeeId>5</d:EmployeeId>
+			<d:EmployeeName>John Field</d:EmployeeName>
+			<d:ManagerId>3</d:ManagerId>
+			<d:RoomId>3</d:RoomId>
+			<d:TeamId>2</d:TeamId>
+			<d:Location m:type="RefScenario.c_Location">
+				<d:City m:type="RefScenario.c_City">
+					<d:PostalCode>69190</d:PostalCode>
+					<d:CityName>Walldorf</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>42</d:Age>
+			<d:EntryDate>2001-02-01T00:00:00</d:EntryDate>
+			<d:ImageUrl>Employees('5')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+	<entry>
+		<id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('6')</id>
+		<title type="text">Susan Bay</title>
+		<updated>2010-12-01T00:00:00Z</updated>
+		<category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+		<link href="Employees('6')" rel="edit" title="Employee"/>
+		<link href="Employees('6')/$value" rel="edit-media" type="image/jpeg"/>
+		<link href="Employees('6')/ne_Manager" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager" title="ne_Manager" type="application/atom+xml;type=entry"/>
+		<link href="Employees('6')/ne_Team" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team" title="ne_Team" type="application/atom+xml;type=entry"/>
+		<link href="Employees('6')/ne_Room" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room" title="ne_Room" type="application/atom+xml;type=entry"/>
+		<content type="image/jpeg" src="Employees('6')/$value"/>
+		<m:properties>
+			<d:EmployeeId>6</d:EmployeeId>
+			<d:EmployeeName>Susan Bay</d:EmployeeName>
+			<d:ManagerId>1</d:ManagerId>
+			<d:RoomId>2</d:RoomId>
+			<d:TeamId>3</d:TeamId>
+			<d:Location m:type="RefScenario.c_Location">
+				<d:City m:type="RefScenario.c_City">
+					<d:PostalCode>69190</d:PostalCode>
+					<d:CityName>Walldorf</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>29</d:Age>
+			<d:EntryDate>2010-12-01T00:00:00</d:EntryDate>
+			<d:ImageUrl>Employees('6')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+	<entry>
+		<id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/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="image/jpeg"/>
+		<link href="Employees('1')/ne_Manager" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager" title="ne_Manager" type="application/atom+xml;type=entry"/>
+		<link href="Employees('1')/ne_Team" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team" title="ne_Team" type="application/atom+xml;type=entry"/>
+		<link href="Employees('1')/ne_Room" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room" title="ne_Room" type="application/atom+xml;type=entry"/>
+		<content type="image/jpeg" 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:City m:type="RefScenario.c_City">
+					<d:PostalCode>69124</d:PostalCode>
+					<d:CityName>Heidelberg</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>52</d:Age>
+			<d:EntryDate>1999-01-01T00:00:00</d:EntryDate>
+			<d:ImageUrl>Employees('1')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+	<entry>
+		<id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('2')</id>
+		<title type="text">Frederic Fall</title>
+		<updated>2003-07-01T00:00:00Z</updated>
+		<category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+		<link href="Employees('2')" rel="edit" title="Employee"/>
+		<link href="Employees('2')/$value" rel="edit-media" type="image/jpeg"/>
+		<link href="Employees('2')/ne_Manager" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager" title="ne_Manager" type="application/atom+xml;type=entry"/>
+		<link href="Employees('2')/ne_Team" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team" title="ne_Team" type="application/atom+xml;type=entry"/>
+		<link href="Employees('2')/ne_Room" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room" title="ne_Room" type="application/atom+xml;type=entry"/>
+		<content type="image/jpeg" src="Employees('2')/$value"/>
+		<m:properties>
+			<d:EmployeeId>2</d:EmployeeId>
+			<d:EmployeeName>Frederic Fall</d:EmployeeName>
+			<d:ManagerId>1</d:ManagerId>
+			<d:RoomId>2</d:RoomId>
+			<d:TeamId>1</d:TeamId>
+			<d:Location m:type="RefScenario.c_Location">
+				<d:City m:type="RefScenario.c_City">
+					<d:PostalCode>69190</d:PostalCode>
+					<d:CityName>Walldorf</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>32</d:Age>
+			<d:EntryDate>2003-07-01T00:00:00</d:EntryDate>
+			<d:ImageUrl>Employees('2')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+	<entry>
+		<id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('3')</id>
+		<title type="text">Jonathan Smith</title>
+		<updated>2013-12-02T12:20:28.622Z</updated>
+		<category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+		<link href="Employees('3')" rel="edit" title="Employee"/>
+		<link href="Employees('3')/$value" rel="edit-media" type="image/jpeg"/>
+		<link href="Employees('3')/ne_Manager" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager" title="ne_Manager" type="application/atom+xml;type=entry"/>
+		<link href="Employees('3')/ne_Team" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team" title="ne_Team" type="application/atom+xml;type=entry"/>
+		<link href="Employees('3')/ne_Room" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room" title="ne_Room" type="application/atom+xml;type=entry"/>
+		<content type="image/jpeg" src="Employees('3')/$value"/>
+		<m:properties>
+			<d:EmployeeId>3</d:EmployeeId>
+			<d:EmployeeName>Jonathan Smith</d:EmployeeName>
+			<d:ManagerId>1</d:ManagerId>
+			<d:RoomId>2</d:RoomId>
+			<d:TeamId>1</d:TeamId>
+			<d:Location m:type="RefScenario.c_Location">
+				<d:City m:type="RefScenario.c_City">
+					<d:PostalCode>69190</d:PostalCode>
+					<d:CityName>Walldorf</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>56</d:Age>
+			<d:EntryDate m:null="true"/>
+			<d:ImageUrl>Employees('3')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+	<entry>
+		<id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('4')</id>
+		<title type="text">Peter Burke</title>
+		<updated>2004-09-12T00:00:00Z</updated>
+		<category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+		<link href="Employees('4')" rel="edit" title="Employee"/>
+		<link href="Employees('4')/$value" rel="edit-media" type="image/jpeg"/>
+		<link href="Employees('4')/ne_Manager" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager" title="ne_Manager" type="application/atom+xml;type=entry"/>
+		<link href="Employees('4')/ne_Team" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team" title="ne_Team" type="application/atom+xml;type=entry"/>
+		<link href="Employees('4')/ne_Room" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room" title="ne_Room" type="application/atom+xml;type=entry"/>
+		<content type="image/jpeg" src="Employees('4')/$value"/>
+		<m:properties>
+			<d:EmployeeId>4</d:EmployeeId>
+			<d:EmployeeName>Peter Burke</d:EmployeeName>
+			<d:ManagerId>3</d:ManagerId>
+			<d:RoomId>2</d:RoomId>
+			<d:TeamId>2</d:TeamId>
+			<d:Location m:type="RefScenario.c_Location">
+				<d:City m:type="RefScenario.c_City">
+					<d:PostalCode>69190</d:PostalCode>
+					<d:CityName>Walldorf</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>39</d:Age>
+			<d:EntryDate>2004-09-12T00:00:00</d:EntryDate>
+			<d:ImageUrl>Employees('4')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+	<entry>
+		<id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('5')</id>
+		<title type="text">John Field</title>
+		<updated>2001-02-01T00:00:00Z</updated>
+		<category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+		<link href="Employees('5')" rel="edit" title="Employee"/>
+		<link href="Employees('5')/$value" rel="edit-media" type="image/jpeg"/>
+		<link href="Employees('5')/ne_Manager" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager" title="ne_Manager" type="application/atom+xml;type=entry"/>
+		<link href="Employees('5')/ne_Team" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team" title="ne_Team" type="application/atom+xml;type=entry"/>
+		<link href="Employees('5')/ne_Room" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room" title="ne_Room" type="application/atom+xml;type=entry"/>
+		<content type="image/jpeg" src="Employees('5')/$value"/>
+		<m:properties>
+			<d:EmployeeId>5</d:EmployeeId>
+			<d:EmployeeName>John Field</d:EmployeeName>
+			<d:ManagerId>3</d:ManagerId>
+			<d:RoomId>3</d:RoomId>
+			<d:TeamId>2</d:TeamId>
+			<d:Location m:type="RefScenario.c_Location">
+				<d:City m:type="RefScenario.c_City">
+					<d:PostalCode>69190</d:PostalCode>
+					<d:CityName>Walldorf</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>42</d:Age>
+			<d:EntryDate>2001-02-01T00:00:00</d:EntryDate>
+			<d:ImageUrl>Employees('5')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+	<entry>
+		<id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('6')</id>
+		<title type="text">Susan Bay</title>
+		<updated>2010-12-01T00:00:00Z</updated>
+		<category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+		<link href="Employees('6')" rel="edit" title="Employee"/>
+		<link href="Employees('6')/$value" rel="edit-media" type="image/jpeg"/>
+		<link href="Employees('6')/ne_Manager" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager" title="ne_Manager" type="application/atom+xml;type=entry"/>
+		<link href="Employees('6')/ne_Team" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team" title="ne_Team" type="application/atom+xml;type=entry"/>
+		<link href="Employees('6')/ne_Room" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room" title="ne_Room" type="application/atom+xml;type=entry"/>
+		<content type="image/jpeg" src="Employees('6')/$value"/>
+		<m:properties>
+			<d:EmployeeId>6</d:EmployeeId>
+			<d:EmployeeName>Susan Bay</d:EmployeeName>
+			<d:ManagerId>1</d:ManagerId>
+			<d:RoomId>2</d:RoomId>
+			<d:TeamId>3</d:TeamId>
+			<d:Location m:type="RefScenario.c_Location">
+				<d:City m:type="RefScenario.c_City">
+					<d:PostalCode>69190</d:PostalCode>
+					<d:CityName>Walldorf</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>29</d:Age>
+			<d:EntryDate>2010-12-01T00:00:00</d:EntryDate>
+			<d:ImageUrl>Employees('6')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+	<entry>
+		<id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/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="image/jpeg"/>
+		<link href="Employees('1')/ne_Manager" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager" title="ne_Manager" type="application/atom+xml;type=entry"/>
+		<link href="Employees('1')/ne_Team" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team" title="ne_Team" type="application/atom+xml;type=entry"/>
+		<link href="Employees('1')/ne_Room" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room" title="ne_Room" type="application/atom+xml;type=entry"/>
+		<content type="image/jpeg" 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:City m:type="RefScenario.c_City">
+					<d:PostalCode>69124</d:PostalCode>
+					<d:CityName>Heidelberg</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>52</d:Age>
+			<d:EntryDate>1999-01-01T00:00:00</d:EntryDate>
+			<d:ImageUrl>Employees('1')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+	<entry>
+		<id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('2')</id>
+		<title type="text">Frederic Fall</title>
+		<updated>2003-07-01T00:00:00Z</updated>
+		<category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+		<link href="Employees('2')" rel="edit" title="Employee"/>
+		<link href="Employees('2')/$value" rel="edit-media" type="image/jpeg"/>
+		<link href="Employees('2')/ne_Manager" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager" title="ne_Manager" type="application/atom+xml;type=entry"/>
+		<link href="Employees('2')/ne_Team" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team" title="ne_Team" type="application/atom+xml;type=entry"/>
+		<link href="Employees('2')/ne_Room" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room" title="ne_Room" type="application/atom+xml;type=entry"/>
+		<content type="image/jpeg" src="Employees('2')/$value"/>
+		<m:properties>
+			<d:EmployeeId>2</d:EmployeeId>
+			<d:EmployeeName>Frederic Fall</d:EmployeeName>
+			<d:ManagerId>1</d:ManagerId>
+			<d:RoomId>2</d:RoomId>
+			<d:TeamId>1</d:TeamId>
+			<d:Location m:type="RefScenario.c_Location">
+				<d:City m:type="RefScenario.c_City">
+					<d:PostalCode>69190</d:PostalCode>
+					<d:CityName>Walldorf</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>32</d:Age>
+			<d:EntryDate>2003-07-01T00:00:00</d:EntryDate>
+			<d:ImageUrl>Employees('2')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+	<entry>
+		<id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('3')</id>
+		<title type="text">Jonathan Smith</title>
+		<updated>2013-12-02T12:20:28.622Z</updated>
+		<category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+		<link href="Employees('3')" rel="edit" title="Employee"/>
+		<link href="Employees('3')/$value" rel="edit-media" type="image/jpeg"/>
+		<link href="Employees('3')/ne_Manager" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager" title="ne_Manager" type="application/atom+xml;type=entry"/>
+		<link href="Employees('3')/ne_Team" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team" title="ne_Team" type="application/atom+xml;type=entry"/>
+		<link href="Employees('3')/ne_Room" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room" title="ne_Room" type="application/atom+xml;type=entry"/>
+		<content type="image/jpeg" src="Employees('3')/$value"/>
+		<m:properties>
+			<d:EmployeeId>3</d:EmployeeId>
+			<d:EmployeeName>Jonathan Smith</d:EmployeeName>
+			<d:ManagerId>1</d:ManagerId>
+			<d:RoomId>2</d:RoomId>
+			<d:TeamId>1</d:TeamId>
+			<d:Location m:type="RefScenario.c_Location">
+				<d:City m:type="RefScenario.c_City">
+					<d:PostalCode>69190</d:PostalCode>
+					<d:CityName>Walldorf</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>56</d:Age>
+			<d:EntryDate m:null="true"/>
+			<d:ImageUrl>Employees('3')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+	<entry>
+		<id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('4')</id>
+		<title type="text">Peter Burke</title>
+		<updated>2004-09-12T00:00:00Z</updated>
+		<category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+		<link href="Employees('4')" rel="edit" title="Employee"/>
+		<link href="Employees('4')/$value" rel="edit-media" type="image/jpeg"/>
+		<link href="Employees('4')/ne_Manager" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager" title="ne_Manager" type="application/atom+xml;type=entry"/>
+		<link href="Employees('4')/ne_Team" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team" title="ne_Team" type="application/atom+xml;type=entry"/>
+		<link href="Employees('4')/ne_Room" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room" title="ne_Room" type="application/atom+xml;type=entry"/>
+		<content type="image/jpeg" src="Employees('4')/$value"/>
+		<m:properties>
+			<d:EmployeeId>4</d:EmployeeId>
+			<d:EmployeeName>Peter Burke</d:EmployeeName>
+			<d:ManagerId>3</d:ManagerId>
+			<d:RoomId>2</d:RoomId>
+			<d:TeamId>2</d:TeamId>
+			<d:Location m:type="RefScenario.c_Location">
+				<d:City m:type="RefScenario.c_City">
+					<d:PostalCode>69190</d:PostalCode>
+					<d:CityName>Walldorf</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>39</d:Age>
+			<d:EntryDate>2004-09-12T00:00:00</d:EntryDate>
+			<d:ImageUrl>Employees('4')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+	<entry>
+		<id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('5')</id>
+		<title type="text">John Field</title>
+		<updated>2001-02-01T00:00:00Z</updated>
+		<category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+		<link href="Employees('5')" rel="edit" title="Employee"/>
+		<link href="Employees('5')/$value" rel="edit-media" type="image/jpeg"/>
+		<link href="Employees('5')/ne_Manager" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager" title="ne_Manager" type="application/atom+xml;type=entry"/>
+		<link href="Employees('5')/ne_Team" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team" title="ne_Team" type="application/atom+xml;type=entry"/>
+		<link href="Employees('5')/ne_Room" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room" title="ne_Room" type="application/atom+xml;type=entry"/>
+		<content type="image/jpeg" src="Employees('5')/$value"/>
+		<m:properties>
+			<d:EmployeeId>5</d:EmployeeId>
+			<d:EmployeeName>John Field</d:EmployeeName>
+			<d:ManagerId>3</d:ManagerId>
+			<d:RoomId>3</d:RoomId>
+			<d:TeamId>2</d:TeamId>
+			<d:Location m:type="RefScenario.c_Location">
+				<d:City m:type="RefScenario.c_City">
+					<d:PostalCode>69190</d:PostalCode>
+					<d:CityName>Walldorf</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>42</d:Age>
+			<d:EntryDate>2001-02-01T00:00:00</d:EntryDate>
+			<d:ImageUrl>Employees('5')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+	<entry>
+		<id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('6')</id>
+		<title type="text">Susan Bay</title>
+		<updated>2010-12-01T00:00:00Z</updated>
+		<category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+		<link href="Employees('6')" rel="edit" title="Employee"/>
+		<link href="Employees('6')/$value" rel="edit-media" type="image/jpeg"/>
+		<link href="Employees('6')/ne_Manager" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager" title="ne_Manager" type="application/atom+xml;type=entry"/>
+		<link href="Employees('6')/ne_Team" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team" title="ne_Team" type="application/atom+xml;type=entry"/>
+		<link href="Employees('6')/ne_Room" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room" title="ne_Room" type="application/atom+xml;type=entry"/>
+		<content type="image/jpeg" src="Employees('6')/$value"/>
+		<m:properties>
+			<d:EmployeeId>6</d:EmployeeId>
+			<d:EmployeeName>Susan Bay</d:EmployeeName>
+			<d:ManagerId>1</d:ManagerId>
+			<d:RoomId>2</d:RoomId>
+			<d:TeamId>3</d:TeamId>
+			<d:Location m:type="RefScenario.c_Location">
+				<d:City m:type="RefScenario.c_City">
+					<d:PostalCode>69190</d:PostalCode>
+					<d:CityName>Walldorf</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>29</d:Age>
+			<d:EntryDate>2010-12-01T00:00:00</d:EntryDate>
+			<d:ImageUrl>Employees('6')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+	<entry>
+		<id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/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="image/jpeg"/>
+		<link href="Employees('1')/ne_Manager" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager" title="ne_Manager" type="application/atom+xml;type=entry"/>
+		<link href="Employees('1')/ne_Team" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team" title="ne_Team" type="application/atom+xml;type=entry"/>
+		<link href="Employees('1')/ne_Room" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room" title="ne_Room" type="application/atom+xml;type=entry"/>
+		<content type="image/jpeg" 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:City m:type="RefScenario.c_City">
+					<d:PostalCode>69124</d:PostalCode>
+					<d:CityName>Heidelberg</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>52</d:Age>
+			<d:EntryDate>1999-01-01T00:00:00</d:EntryDate>
+			<d:ImageUrl>Employees('1')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+	<entry>
+		<id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('2')</id>
+		<title type="text">Frederic Fall</title>
+		<updated>2003-07-01T00:00:00Z</updated>
+		<category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+		<link href="Employees('2')" rel="edit" title="Employee"/>
+		<link href="Employees('2')/$value" rel="edit-media" type="image/jpeg"/>
+		<link href="Employees('2')/ne_Manager" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager" title="ne_Manager" type="application/atom+xml;type=entry"/>
+		<link href="Employees('2')/ne_Team" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team" title="ne_Team" type="application/atom+xml;type=entry"/>
+		<link href="Employees('2')/ne_Room" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room" title="ne_Room" type="application/atom+xml;type=entry"/>
+		<content type="image/jpeg" src="Employees('2')/$value"/>
+		<m:properties>
+			<d:EmployeeId>2</d:EmployeeId>
+			<d:EmployeeName>Frederic Fall</d:EmployeeName>
+			<d:ManagerId>1</d:ManagerId>
+			<d:RoomId>2</d:RoomId>
+			<d:TeamId>1</d:TeamId>
+			<d:Location m:type="RefScenario.c_Location">
+				<d:City m:type="RefScenario.c_City">
+					<d:PostalCode>69190</d:PostalCode>
+					<d:CityName>Walldorf</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>32</d:Age>
+			<d:EntryDate>2003-07-01T00:00:00</d:EntryDate>
+			<d:ImageUrl>Employees('2')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+	<entry>
+		<id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('3')</id>
+		<title type="text">Jonathan Smith</title>
+		<updated>2013-12-02T12:20:28.622Z</updated>
+		<category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+		<link href="Employees('3')" rel="edit" title="Employee"/>
+		<link href="Employees('3')/$value" rel="edit-media" type="image/jpeg"/>
+		<link href="Employees('3')/ne_Manager" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager" title="ne_Manager" type="application/atom+xml;type=entry"/>
+		<link href="Employees('3')/ne_Team" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team" title="ne_Team" type="application/atom+xml;type=entry"/>
+		<link href="Employees('3')/ne_Room" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room" title="ne_Room" type="application/atom+xml;type=entry"/>
+		<content type="image/jpeg" src="Employees('3')/$value"/>
+		<m:properties>
+			<d:EmployeeId>3</d:EmployeeId>
+			<d:EmployeeName>Jonathan Smith</d:EmployeeName>
+			<d:ManagerId>1</d:ManagerId>
+			<d:RoomId>2</d:RoomId>
+			<d:TeamId>1</d:TeamId>
+			<d:Location m:type="RefScenario.c_Location">
+				<d:City m:type="RefScenario.c_City">
+					<d:PostalCode>69190</d:PostalCode>
+					<d:CityName>Walldorf</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>56</d:Age>
+			<d:EntryDate m:null="true"/>
+			<d:ImageUrl>Employees('3')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+	<entry>
+		<id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('4')</id>
+		<title type="text">Peter Burke</title>
+		<updated>2004-09-12T00:00:00Z</updated>
+		<category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+		<link href="Employees('4')" rel="edit" title="Employee"/>
+		<link href="Employees('4')/$value" rel="edit-media" type="image/jpeg"/>
+		<link href="Employees('4')/ne_Manager" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager" title="ne_Manager" type="application/atom+xml;type=entry"/>
+		<link href="Employees('4')/ne_Team" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team" title="ne_Team" type="application/atom+xml;type=entry"/>
+		<link href="Employees('4')/ne_Room" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room" title="ne_Room" type="application/atom+xml;type=entry"/>
+		<content type="image/jpeg" src="Employees('4')/$value"/>
+		<m:properties>
+			<d:EmployeeId>4</d:EmployeeId>
+			<d:EmployeeName>Peter Burke</d:EmployeeName>
+			<d:ManagerId>3</d:ManagerId>
+			<d:RoomId>2</d:RoomId>
+			<d:TeamId>2</d:TeamId>
+			<d:Location m:type="RefScenario.c_Location">
+				<d:City m:type="RefScenario.c_City">
+					<d:PostalCode>69190</d:PostalCode>
+					<d:CityName>Walldorf</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>39</d:Age>
+			<d:EntryDate>2004-09-12T00:00:00</d:EntryDate>
+			<d:ImageUrl>Employees('4')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+	<entry>
+		<id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('5')</id>
+		<title type="text">John Field</title>
+		<updated>2001-02-01T00:00:00Z</updated>
+		<category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+		<link href="Employees('5')" rel="edit" title="Employee"/>
+		<link href="Employees('5')/$value" rel="edit-media" type="image/jpeg"/>
+		<link href="Employees('5')/ne_Manager" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager" title="ne_Manager" type="application/atom+xml;type=entry"/>
+		<link href="Employees('5')/ne_Team" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team" title="ne_Team" type="application/atom+xml;type=entry"/>
+		<link href="Employees('5')/ne_Room" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room" title="ne_Room" type="application/atom+xml;type=entry"/>
+		<content type="image/jpeg" src="Employees('5')/$value"/>
+		<m:properties>
+			<d:EmployeeId>5</d:EmployeeId>
+			<d:EmployeeName>John Field</d:EmployeeName>
+			<d:ManagerId>3</d:ManagerId>
+			<d:RoomId>3</d:RoomId>
+			<d:TeamId>2</d:TeamId>
+			<d:Location m:type="RefScenario.c_Location">
+				<d:City m:type="RefScenario.c_City">
+					<d:PostalCode>69190</d:PostalCode>
+					<d:CityName>Walldorf</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>42</d:Age>
+			<d:EntryDate>2001-02-01T00:00:00</d:EntryDate>
+			<d:ImageUrl>Employees('5')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+	<entry>
+		<id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('6')</id>
+		<title type="text">Susan Bay</title>
+		<updated>2010-12-01T00:00:00Z</updated>
+		<category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+		<link href="Employees('6')" rel="edit" title="Employee"/>
+		<link href="Employees('6')/$value" rel="edit-media" type="image/jpeg"/>
+		<link href="Employees('6')/ne_Manager" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager" title="ne_Manager" type="application/atom+xml;type=entry"/>
+		<link href="Employees('6')/ne_Team" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team" title="ne_Team" type="application/atom+xml;type=entry"/>
+		<link href="Employees('6')/ne_Room" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room" title="ne_Room" type="application/atom+xml;type=entry"/>
+		<content type="image/jpeg" src="Employees('6')/$value"/>
+		<m:properties>
+			<d:EmployeeId>6</d:EmployeeId>
+			<d:EmployeeName>Susan Bay</d:EmployeeName>
+			<d:ManagerId>1</d:ManagerId>
+			<d:RoomId>2</d:RoomId>
+			<d:TeamId>3</d:TeamId>
+			<d:Location m:type="RefScenario.c_Location">
+				<d:City m:type="RefScenario.c_City">
+					<d:PostalCode>69190</d:PostalCode>
+					<d:CityName>Walldorf</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>29</d:Age>
+			<d:EntryDate>2010-12-01T00:00:00</d:EntryDate>
+			<d:ImageUrl>Employees('6')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+	<entry>
+		<id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/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="image/jpeg"/>
+		<link href="Employees('1')/ne_Manager" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager" title="ne_Manager" type="application/atom+xml;type=entry"/>
+		<link href="Employees('1')/ne_Team" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team" title="ne_Team" type="application/atom+xml;type=entry"/>
+		<link href="Employees('1')/ne_Room" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room" title="ne_Room" type="application/atom+xml;type=entry"/>
+		<content type="image/jpeg" 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:City m:type="RefScenario.c_City">
+					<d:PostalCode>69124</d:PostalCode>
+					<d:CityName>Heidelberg</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>52</d:Age>
+			<d:EntryDate>1999-01-01T00:00:00</d:EntryDate>
+			<d:ImageUrl>Employees('1')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+	<entry>
+		<id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('2')</id>
+		<title type="text">Frederic Fall</title>
+		<updated>2003-07-01T00:00:00Z</updated>
+		<category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+		<link href="Employees('2')" rel="edit" title="Employee"/>
+		<link href="Employees('2')/$value" rel="edit-media" type="image/jpeg"/>
+		<link href="Employees('2')/ne_Manager" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager" title="ne_Manager" type="application/atom+xml;type=entry"/>
+		<link href="Employees('2')/ne_Team" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team" title="ne_Team" type="application/atom+xml;type=entry"/>
+		<link href="Employees('2')/ne_Room" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room" title="ne_Room" type="application/atom+xml;type=entry"/>
+		<content type="image/jpeg" src="Employees('2')/$value"/>
+		<m:properties>
+			<d:EmployeeId>2</d:EmployeeId>
+			<d:EmployeeName>Frederic Fall</d:EmployeeName>
+			<d:ManagerId>1</d:ManagerId>
+			<d:RoomId>2</d:RoomId>
+			<d:TeamId>1</d:TeamId>
+			<d:Location m:type="RefScenario.c_Location">
+				<d:City m:type="RefScenario.c_City">
+					<d:PostalCode>69190</d:PostalCode>
+					<d:CityName>Walldorf</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>32</d:Age>
+			<d:EntryDate>2003-07-01T00:00:00</d:EntryDate>
+			<d:ImageUrl>Employees('2')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+	<entry>
+		<id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('3')</id>
+		<title type="text">Jonathan Smith</title>
+		<updated>2013-12-02T12:20:28.622Z</updated>
+		<category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+		<link href="Employees('3')" rel="edit" title="Employee"/>
+		<link href="Employees('3')/$value" rel="edit-media" type="image/jpeg"/>
+		<link href="Employees('3')/ne_Manager" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager" title="ne_Manager" type="application/atom+xml;type=entry"/>
+		<link href="Employees('3')/ne_Team" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team" title="ne_Team" type="application/atom+xml;type=entry"/>
+		<link href="Employees('3')/ne_Room" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room" title="ne_Room" type="application/atom+xml;type=entry"/>
+		<content type="image/jpeg" src="Employees('3')/$value"/>
+		<m:properties>
+			<d:EmployeeId>3</d:EmployeeId>
+			<d:EmployeeName>Jonathan Smith</d:EmployeeName>
+			<d:ManagerId>1</d:ManagerId>
+			<d:RoomId>2</d:RoomId>
+			<d:TeamId>1</d:TeamId>
+			<d:Location m:type="RefScenario.c_Location">
+				<d:City m:type="RefScenario.c_City">
+					<d:PostalCode>69190</d:PostalCode>
+					<d:CityName>Walldorf</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>56</d:Age>
+			<d:EntryDate m:null="true"/>
+			<d:ImageUrl>Employees('3')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+	<entry>
+		<id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('4')</id>
+		<title type="text">Peter Burke</title>
+		<updated>2004-09-12T00:00:00Z</updated>
+		<category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+		<link href="Employees('4')" rel="edit" title="Employee"/>
+		<link href="Employees('4')/$value" rel="edit-media" type="image/jpeg"/>
+		<link href="Employees('4')/ne_Manager" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager" title="ne_Manager" type="application/atom+xml;type=entry"/>
+		<link href="Employees('4')/ne_Team" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team" title="ne_Team" type="application/atom+xml;type=entry"/>
+		<link href="Employees('4')/ne_Room" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room" title="ne_Room" type="application/atom+xml;type=entry"/>
+		<content type="image/jpeg" src="Employees('4')/$value"/>
+		<m:properties>
+			<d:EmployeeId>4</d:EmployeeId>
+			<d:EmployeeName>Peter Burke</d:EmployeeName>
+			<d:ManagerId>3</d:ManagerId>
+			<d:RoomId>2</d:RoomId>
+			<d:TeamId>2</d:TeamId>
+			<d:Location m:type="RefScenario.c_Location">
+				<d:City m:type="RefScenario.c_City">
+					<d:PostalCode>69190</d:PostalCode>
+					<d:CityName>Walldorf</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>39</d:Age>
+			<d:EntryDate>2004-09-12T00:00:00</d:EntryDate>
+			<d:ImageUrl>Employees('4')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+	<entry>
+		<id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('5')</id>
+		<title type="text">John Field</title>
+		<updated>2001-02-01T00:00:00Z</updated>
+		<category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+		<link href="Employees('5')" rel="edit" title="Employee"/>
+		<link href="Employees('5')/$value" rel="edit-media" type="image/jpeg"/>
+		<link href="Employees('5')/ne_Manager" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager" title="ne_Manager" type="application/atom+xml;type=entry"/>
+		<link href="Employees('5')/ne_Team" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team" title="ne_Team" type="application/atom+xml;type=entry"/>
+		<link href="Employees('5')/ne_Room" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room" title="ne_Room" type="application/atom+xml;type=entry"/>
+		<content type="image/jpeg" src="Employees('5')/$value"/>
+		<m:properties>
+			<d:EmployeeId>5</d:EmployeeId>
+			<d:EmployeeName>John Field</d:EmployeeName>
+			<d:ManagerId>3</d:ManagerId>
+			<d:RoomId>3</d:RoomId>
+			<d:TeamId>2</d:TeamId>
+			<d:Location m:type="RefScenario.c_Location">
+				<d:City m:type="RefScenario.c_City">
+					<d:PostalCode>69190</d:PostalCode>
+					<d:CityName>Walldorf</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>42</d:Age>
+			<d:EntryDate>2001-02-01T00:00:00</d:EntryDate>
+			<d:ImageUrl>Employees('5')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+	<entry>
+		<id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('6')</id>
+		<title type="text">Susan Bay</title>
+		<updated>2010-12-01T00:00:00Z</updated>
+		<category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+		<link href="Employees('6')" rel="edit" title="Employee"/>
+		<link href="Employees('6')/$value" rel="edit-media" type="image/jpeg"/>
+		<link href="Employees('6')/ne_Manager" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager" title="ne_Manager" type="application/atom+xml;type=entry"/>
+		<link href="Employees('6')/ne_Team" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team" title="ne_Team" type="application/atom+xml;type=entry"/>
+		<link href="Employees('6')/ne_Room" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room" title="ne_Room" type="application/atom+xml;type=entry"/>
+		<content type="image/jpeg" src="Employees('6')/$value"/>
+		<m:properties>
+			<d:EmployeeId>6</d:EmployeeId>
+			<d:EmployeeName>Susan Bay</d:EmployeeName>
+			<d:ManagerId>1</d:ManagerId>
+			<d:RoomId>2</d:RoomId>
+			<d:TeamId>3</d:TeamId>
+			<d:Location m:type="RefScenario.c_Location">
+				<d:City m:type="RefScenario.c_City">
+					<d:PostalCode>69190</d:PostalCode>
+					<d:CityName>Walldorf</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>29</d:Age>
+			<d:EntryDate>2010-12-01T00:00:00</d:EntryDate>
+			<d:ImageUrl>Employees('6')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+	<entry>
+		<id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/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="image/jpeg"/>
+		<link href="Employees('1')/ne_Manager" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager" title="ne_Manager" type="application/atom+xml;type=entry"/>
+		<link href="Employees('1')/ne_Team" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team" title="ne_Team" type="application/atom+xml;type=entry"/>
+		<link href="Employees('1')/ne_Room" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room" title="ne_Room" type="application/atom+xml;type=entry"/>
+		<content type="image/jpeg" 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:City m:type="RefScenario.c_City">
+					<d:PostalCode>69124</d:PostalCode>
+					<d:CityName>Heidelberg</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>52</d:Age>
+			<d:EntryDate>1999-01-01T00:00:00</d:EntryDate>
+			<d:ImageUrl>Employees('1')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+	<entry>
+		<id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('2')</id>
+		<title type="text">Frederic Fall</title>
+		<updated>2003-07-01T00:00:00Z</updated>
+		<category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+		<link href="Employees('2')" rel="edit" title="Employee"/>
+		<link href="Employees('2')/$value" rel="edit-media" type="image/jpeg"/>
+		<link href="Employees('2')/ne_Manager" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager" title="ne_Manager" type="application/atom+xml;type=entry"/>
+		<link href="Employees('2')/ne_Team" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team" title="ne_Team" type="application/atom+xml;type=entry"/>
+		<link href="Employees('2')/ne_Room" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room" title="ne_Room" type="application/atom+xml;type=entry"/>
+		<content type="image/jpeg" src="Employees('2')/$value"/>
+		<m:properties>
+			<d:EmployeeId>2</d:EmployeeId>
+			<d:EmployeeName>Frederic Fall</d:EmployeeName>
+			<d:ManagerId>1</d:ManagerId>
+			<d:RoomId>2</d:RoomId>
+			<d:TeamId>1</d:TeamId>
+			<d:Location m:type="RefScenario.c_Location">
+				<d:City m:type="RefScenario.c_City">
+					<d:PostalCode>69190</d:PostalCode>
+					<d:CityName>Walldorf</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>32</d:Age>
+			<d:EntryDate>2003-07-01T00:00:00</d:EntryDate>
+			<d:ImageUrl>Employees('2')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+	<entry>
+		<id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('3')</id>
+		<title type="text">Jonathan Smith</title>
+		<updated>2013-12-02T12:20:28.622Z</updated>
+		<category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+		<link href="Employees('3')" rel="edit" title="Employee"/>
+		<link href="Employees('3')/$value" rel="edit-media" type="image/jpeg"/>
+		<link href="Employees('3')/ne_Manager" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager" title="ne_Manager" type="application/atom+xml;type=entry"/>
+		<link href="Employees('3')/ne_Team" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team" title="ne_Team" type="application/atom+xml;type=entry"/>
+		<link href="Employees('3')/ne_Room" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room" title="ne_Room" type="application/atom+xml;type=entry"/>
+		<content type="image/jpeg" src="Employees('3')/$value"/>
+		<m:properties>
+			<d:EmployeeId>3</d:EmployeeId>
+			<d:EmployeeName>Jonathan Smith</d:EmployeeName>
+			<d:ManagerId>1</d:ManagerId>
+			<d:RoomId>2</d:RoomId>
+			<d:TeamId>1</d:TeamId>
+			<d:Location m:type="RefScenario.c_Location">
+				<d:City m:type="RefScenario.c_City">
+					<d:PostalCode>69190</d:PostalCode>
+					<d:CityName>Walldorf</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>56</d:Age>
+			<d:EntryDate m:null="true"/>
+			<d:ImageUrl>Employees('3')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+	<entry>
+		<id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('4')</id>
+		<title type="text">Peter Burke</title>
+		<updated>2004-09-12T00:00:00Z</updated>
+		<category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+		<link href="Employees('4')" rel="edit" title="Employee"/>
+		<link href="Employees('4')/$value" rel="edit-media" type="image/jpeg"/>
+		<link href="Employees('4')/ne_Manager" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager" title="ne_Manager" type="application/atom+xml;type=entry"/>
+		<link href="Employees('4')/ne_Team" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team" title="ne_Team" type="application/atom+xml;type=entry"/>
+		<link href="Employees('4')/ne_Room" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room" title="ne_Room" type="application/atom+xml;type=entry"/>
+		<content type="image/jpeg" src="Employees('4')/$value"/>
+		<m:properties>
+			<d:EmployeeId>4</d:EmployeeId>
+			<d:EmployeeName>Peter Burke</d:EmployeeName>
+			<d:ManagerId>3</d:ManagerId>
+			<d:RoomId>2</d:RoomId>
+			<d:TeamId>2</d:TeamId>
+			<d:Location m:type="RefScenario.c_Location">
+				<d:City m:type="RefScenario.c_City">
+					<d:PostalCode>69190</d:PostalCode>
+					<d:CityName>Walldorf</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>39</d:Age>
+			<d:EntryDate>2004-09-12T00:00:00</d:EntryDate>
+			<d:ImageUrl>Employees('4')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+	<entry>
+		<id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('5')</id>
+		<title type="text">John Field</title>
+		<updated>2001-02-01T00:00:00Z</updated>
+		<category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+		<link href="Employees('5')" rel="edit" title="Employee"/>
+		<link href="Employees('5')/$value" rel="edit-media" type="image/jpeg"/>
+		<link href="Employees('5')/ne_Manager" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager" title="ne_Manager" type="application/atom+xml;type=entry"/>
+		<link href="Employees('5')/ne_Team" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team" title="ne_Team" type="application/atom+xml;type=entry"/>
+		<link href="Employees('5')/ne_Room" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room" title="ne_Room" type="application/atom+xml;type=entry"/>
+		<content type="image/jpeg" src="Employees('5')/$value"/>
+		<m:properties>
+			<d:EmployeeId>5</d:EmployeeId>
+			<d:EmployeeName>John Field</d:EmployeeName>
+			<d:ManagerId>3</d:ManagerId>
+			<d:RoomId>3</d:RoomId>
+			<d:TeamId>2</d:TeamId>
+			<d:Location m:type="RefScenario.c_Location">
+				<d:City m:type="RefScenario.c_City">
+					<d:PostalCode>69190</d:PostalCode>
+					<d:CityName>Walldorf</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>42</d:Age>
+			<d:EntryDate>2001-02-01T00:00:00</d:EntryDate>
+			<d:ImageUrl>Employees('5')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+	<entry>
+		<id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('6')</id>
+		<title type="text">Susan Bay</title>
+		<updated>2010-12-01T00:00:00Z</updated>
+		<category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+		<link href="Employees('6')" rel="edit" title="Employee"/>
+		<link href="Employees('6')/$value" rel="edit-media" type="image/jpeg"/>
+		<link href="Employees('6')/ne_Manager" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager" title="ne_Manager" type="application/atom+xml;type=entry"/>
+		<link href="Employees('6')/ne_Team" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team" title="ne_Team" type="application/atom+xml;type=entry"/>
+		<link href="Employees('6')/ne_Room" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room" title="ne_Room" type="application/atom+xml;type=entry"/>
+		<content type="image/jpeg" src="Employees('6')/$value"/>
+		<m:properties>
+			<d:EmployeeId>6</d:EmployeeId>
+			<d:EmployeeName>Susan Bay</d:EmployeeName>
+			<d:ManagerId>1</d:ManagerId>
+			<d:RoomId>2</d:RoomId>
+			<d:TeamId>3</d:TeamId>
+			<d:Location m:type="RefScenario.c_Location">
+				<d:City m:type="RefScenario.c_City">
+					<d:PostalCode>69190</d:PostalCode>
+					<d:CityName>Walldorf</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>29</d:Age>
+			<d:EntryDate>2010-12-01T00:00:00</d:EntryDate>
+			<d:ImageUrl>Employees('6')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+	<entry>
+		<id>https://olin

<TRUNCATED>

[23/24] olingo-odata2 git commit: [OLINGO-1253]Client Module for Olingo v2

Posted by ar...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/pom.xml
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/pom.xml b/odata2-lib/odata-client-core/pom.xml
new file mode 100644
index 0000000..e63401b
--- /dev/null
+++ b/odata2-lib/odata-client-core/pom.xml
@@ -0,0 +1,90 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+
+	<parent>
+		<groupId>org.apache.olingo</groupId>
+		<artifactId>olingo-odata2-lib</artifactId>
+		<version>2.0.11-SNAPSHOT</version>
+		<relativePath>..</relativePath>
+	</parent>
+
+	<artifactId>olingo-odata2-client-core</artifactId>
+	<packaging>jar</packaging>
+	<name>${project.artifactId}</name>
+
+
+	<dependencies>
+	  <dependency>
+              <groupId>junit</groupId>
+              <artifactId>junit</artifactId>
+              <version>${junit.version}</version>
+          </dependency>
+          <dependency>
+			<groupId>org.apache.olingo</groupId>
+			<artifactId>olingo-odata2-client-api</artifactId>
+			<version>${project.version}</version>
+		</dependency> 
+		<dependency>
+			<groupId>org.apache.olingo</groupId>
+			<artifactId>olingo-odata2-core</artifactId>
+			<version>${project.version}</version>
+		</dependency> 
+		 <dependency>
+            <groupId>org.apache.olingo</groupId>
+            <artifactId>olingo-odata2-testutil</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>xmlunit</groupId>
+            <artifactId>xmlunit</artifactId>
+            <scope>test</scope>
+        </dependency>
+	    <dependency>
+	      <groupId>org.apache.httpcomponents</groupId>
+	      <artifactId>httpcore</artifactId>
+	      <version>${httpcore.version}</version>
+	    </dependency>
+	</dependencies>
+	<build>
+		<plugins>
+			<plugin>
+				<artifactId>maven-jar-plugin</artifactId>
+				<configuration>
+					<archive>
+						<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
+					</archive>
+				</configuration>
+			</plugin>
+			<plugin>
+				<groupId>org.apache.felix</groupId>
+				<artifactId>maven-bundle-plugin</artifactId>
+				<extensions>true</extensions>
+				<executions>
+					<execution>
+						<id>bundle-manifest</id>
+						<phase>process-classes</phase>
+						<goals>
+							<goal>manifest</goal>
+						</goals>
+					</execution>
+				</executions>
+				<configuration>
+					<instructions>
+						<Import-Package>
+							*
+						</Import-Package>
+						<Export-Package>
+						</Export-Package>
+						<Bundle-DocURL>${project.url}</Bundle-DocURL>
+						<Bundle-ActivationPolicy>lazy</Bundle-ActivationPolicy>
+						<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
+					</instructions>
+				</configuration>
+			</plugin>
+		</plugins>
+	</build>
+
+
+</project>

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ODataClientImpl.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ODataClientImpl.java b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ODataClientImpl.java
new file mode 100644
index 0000000..1a51999
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ODataClientImpl.java
@@ -0,0 +1,199 @@
+package org.apache.olingo.odata2.client.core;
+
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.exception.ODataNotAcceptableException;
+import org.apache.olingo.odata2.api.uri.PathSegment;
+import org.apache.olingo.odata2.api.uri.UriInfo;
+import org.apache.olingo.odata2.api.uri.UriNotMatchingException;
+import org.apache.olingo.odata2.api.uri.UriSyntaxException;
+import org.apache.olingo.odata2.client.api.ODataClient;
+import org.apache.olingo.odata2.client.api.edm.EdmDataServices;
+import org.apache.olingo.odata2.client.api.ep.ContentTypeBasedDeserializer;
+import org.apache.olingo.odata2.client.api.ep.ContentTypeBasedSerializer;
+import org.apache.olingo.odata2.client.api.ep.DeserializerMetadataProviderInterface;
+import org.apache.olingo.odata2.client.api.uri.EdmURIBuilder;
+import org.apache.olingo.odata2.client.api.uri.URIBuilder;
+import org.apache.olingo.odata2.client.core.ep.AtomSerializerDeserializer;
+import org.apache.olingo.odata2.client.core.ep.JsonSerializerDeserializer;
+import org.apache.olingo.odata2.client.core.ep.deserializer.XmlMetadataDeserializer;
+import org.apache.olingo.odata2.client.core.uri.EdmURIBuilderImpl;
+import org.apache.olingo.odata2.client.core.uri.URIBuilderImpl;
+import org.apache.olingo.odata2.core.ODataPathSegmentImpl;
+import org.apache.olingo.odata2.core.commons.ContentType;
+import org.apache.olingo.odata2.core.uri.UriParserImpl;
+
+/**
+ * Implementation class to obtain serializers and deserializers based on content type
+ *
+ */
+public class ODataClientImpl extends ODataClient implements DeserializerMetadataProviderInterface{
+
+  private static final String AMP = "&";
+  private static final String EQUAL = "=";
+  private static final String QUESTIONMARK = "\\?";
+  private static final String SLASH = "/";
+  
+  @Override
+  public ContentTypeBasedSerializer createSerializer(final String contentType) 
+      throws EntityProviderException {
+    return createSerializer(ContentType.createAsCustom(contentType));
+
+  }
+
+  private ContentTypeBasedSerializer createSerializer(ContentType contentType)
+      throws EntityProviderException {
+    try {
+      switch (contentType.getODataFormat()) {
+      case ATOM:
+      case XML:
+        return new AtomSerializerDeserializer(contentType.getODataFormat());
+      case JSON:
+        return new JsonSerializerDeserializer();
+      default:
+        throw new ODataNotAcceptableException(ODataNotAcceptableException.NOT_SUPPORTED_CONTENT_TYPE
+            .addContent(contentType));
+      }
+    } catch (final ODataNotAcceptableException e) {
+      throw new EntityProviderException(EntityProviderException.COMMON, e);
+    }
+  }
+  
+  @Override
+  public ContentTypeBasedDeserializer createDeserializer(final String contentType) 
+      throws EntityProviderException {
+    return createDeserializer(ContentType.createAsCustom(contentType));
+
+  }
+
+  private ContentTypeBasedDeserializer createDeserializer(ContentType contentType)
+      throws EntityProviderException {
+    try {
+      switch (contentType.getODataFormat()) {
+      case ATOM:
+      case XML:
+        return new AtomSerializerDeserializer(contentType.getODataFormat());
+      case JSON:
+        return new JsonSerializerDeserializer();
+      default:
+        throw new ODataNotAcceptableException(ODataNotAcceptableException.NOT_SUPPORTED_CONTENT_TYPE
+            .addContent(contentType));
+      }
+    } catch (final ODataNotAcceptableException e) {
+      throw new EntityProviderException(EntityProviderException.COMMON, e);
+    }
+  }
+
+  @Override
+  public EdmDataServices readMetadata(InputStream content, boolean validate) 
+      throws EntityProviderException, EdmException {
+    return new XmlMetadataDeserializer().readMetadata(content, validate);
+  }
+
+  @Override
+  public UriInfo parseUri(Edm edm, List<PathSegment> pathSegments, Map<String, List<String>> queryParameters)
+      throws UriSyntaxException, UriNotMatchingException, EdmException {
+    return new UriParserImpl(edm).parseAll(pathSegments, queryParameters);
+  }
+
+  @Override
+  public UriInfo parseUri(Edm edm, String uri) throws UriSyntaxException, UriNotMatchingException, EdmException {
+    final String[] path = uri.split(QUESTIONMARK, -1);
+    if (path.length > 2) {
+      throw new UriSyntaxException(UriSyntaxException.URISYNTAX);
+    }
+
+    final List<PathSegment> pathSegments = getPathSegments(path[0]);
+    
+    Map<String, List<String>> queryParameters;
+    if (path.length == 2) {
+      queryParameters = getQueryParameters(unescape(path[1]));
+    } else {
+      queryParameters = new HashMap<String, List<String>>();
+    }
+    
+    return new UriParserImpl(edm).parseAll(pathSegments, queryParameters);
+  }
+  /**
+   * Fetch query parameters
+   * @param uri
+   * @return
+   */
+  private Map<String, List<String>> getQueryParameters(final String uri) {
+    Map<String, List<String>> allQueryParameters = new HashMap<String, List<String>>();
+
+    for (final String option : uri.split(AMP)) {
+      final String[] keyAndValue = option.split(EQUAL);
+      List<String> list = allQueryParameters.containsKey(keyAndValue[0]) ?
+          allQueryParameters.get(keyAndValue[0]) : new LinkedList<String>();
+
+      list.add(keyAndValue.length == 2 ? keyAndValue[1] : "");
+
+      allQueryParameters.put(keyAndValue[0], list);
+    }
+
+    return allQueryParameters;
+  }
+  /**
+   * Fetch path segments
+   * @param uri
+   * @return
+   * @throws UriSyntaxException
+   */
+  private List<PathSegment> getPathSegments(final String uri) throws UriSyntaxException {
+    List<PathSegment> pathSegments = new ArrayList<PathSegment>();
+    for (final String segment : uri.split(SLASH, -1)) {
+      final String unescapedSegment = unescape(segment);
+      PathSegment oDataSegment = new ODataPathSegmentImpl(unescapedSegment, null);
+      pathSegments.add(oDataSegment);
+    }
+    return pathSegments;
+  }
+  
+  private String unescape(final String s) throws UriSyntaxException {
+    try {
+      return new URI(s).getPath();
+    } catch (URISyntaxException e) {
+      throw new UriSyntaxException(UriSyntaxException.NOTEXT, e);
+    }
+  }
+
+  
+/**
+ * Fetch Query parameters 
+ * @param uri
+ * @return
+ */
+  private Map<String, String> getQueryParametersWithStrictFilter(String uri) {
+    Map<String, String> queryParameters = new HashMap<String, String>();
+    for (final String option : uri.split(AMP)) {
+      final String[] keyAndValue = option.split(EQUAL);
+      if (keyAndValue.length == 2) {
+        queryParameters.put(keyAndValue[0], keyAndValue[1]);
+      } else {
+        queryParameters.put(keyAndValue[0], "");
+      }
+    }
+    return queryParameters;
+  }
+
+@Override
+  public EdmURIBuilder edmUriBuilder(String serviceRoot) {
+    return new EdmURIBuilderImpl(serviceRoot);
+  }
+
+@Override
+  public URIBuilder uriBuilder(String serviceRoot) {
+    return new URIBuilderImpl(serviceRoot);
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/EdmMetadataAssociationEnd.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/EdmMetadataAssociationEnd.java b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/EdmMetadataAssociationEnd.java
new file mode 100644
index 0000000..dacb8d3
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/EdmMetadataAssociationEnd.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * 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.client.core.edm;
+
+import org.apache.olingo.odata2.api.edm.EdmAssociationEnd;
+
+/**
+ * @org.apache.olingo.odata2.DoNotImplement
+ * A CSDL AssociationEnd element
+ * 
+ * <p>EdmAssociationEnd defines one side of the relationship of two entity types.
+ * 
+ */
+public interface EdmMetadataAssociationEnd extends EdmAssociationEnd {
+
+
+  /**
+   * @return {@link OnDelete} on delete
+   */
+  public EdmOnDelete getOnDelete() ;
+  
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/EdmOnDelete.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/EdmOnDelete.java b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/EdmOnDelete.java
new file mode 100644
index 0000000..0a39db6
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/EdmOnDelete.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * 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.client.core.edm;
+
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.EdmAction;
+import org.apache.olingo.odata2.api.edm.EdmAnnotationAttribute;
+import org.apache.olingo.odata2.api.edm.EdmAnnotationElement;
+import org.apache.olingo.odata2.client.api.edm.EdmDocumentation;
+
+/**
+ * Objects of this class represent an OnDelete Action
+ * 
+ */
+public interface EdmOnDelete {
+  /**
+   * @return {@link EdmAction} action
+   */
+  public EdmAction getAction() ;
+
+  /**
+   * @return {@link Documentation} documentation
+   */
+  public EdmDocumentation getDocumentation() ;
+
+  /**
+   * @return List of {@link AnnotationAttribute} annotation attributes
+   */
+  public List<EdmAnnotationAttribute> getAnnotationAttributes();
+
+  /**
+   * @return List of {@link AnnotationElement} annotation elements
+   */
+  public List<EdmAnnotationElement> getAnnotationElements() ;
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmAnnotationAttributeImpl.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmAnnotationAttributeImpl.java b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmAnnotationAttributeImpl.java
new file mode 100644
index 0000000..7675a41
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmAnnotationAttributeImpl.java
@@ -0,0 +1,99 @@
+/*******************************************************************************
+ * 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.client.core.edm.Impl;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmAnnotationAttribute;
+
+/**
+ * Objects of this class represent an annotation attribute
+ * 
+ */
+public class EdmAnnotationAttributeImpl implements EdmAnnotationAttribute {
+
+  private String namespace;
+  private String prefix;
+  private String name;
+  private String text;
+
+  @Override
+  public String getNamespace() {
+    return namespace;
+  }
+
+  @Override
+  public String getPrefix() {
+    return prefix;
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+
+  @Override
+  public String getText() {
+    return text;
+  }
+
+  /**
+   * Sets the namespace for this {@link EdmAnnotationAttributeImpl}.
+   * @param namespace
+   * @return {@link EdmAnnotationAttributeImpl} for method chaining
+   */
+  public EdmAnnotationAttributeImpl setNamespace(final String namespace) {
+    this.namespace = namespace;
+    return this;
+  }
+
+  /**
+   * Sets the prefix for this {@link EdmAnnotationAttributeImpl}.
+   * @param prefix
+   * @return {@link EdmAnnotationAttributeImpl} for method chaining
+   */
+  public EdmAnnotationAttributeImpl setPrefix(final String prefix) {
+    this.prefix = prefix;
+    return this;
+  }
+
+  /**
+   * Sets the name for this {@link EdmAnnotationAttributeImpl}.
+   * @param name
+   * @return {@link EdmAnnotationAttributeImpl} for method chaining
+   */
+  public EdmAnnotationAttributeImpl setName(final String name) {
+    this.name = name;
+    return this;
+  }
+
+  /**
+   * Sets the text for this {@link EdmAnnotationAttributeImpl}.
+   * @param text
+   * @return {@link EdmAnnotationAttributeImpl} for method chaining
+   */
+  public EdmAnnotationAttributeImpl setText(final String text) {
+    this.text = text;
+    return this;
+  }
+
+  @Override
+  public String toString() {
+    return namespace + Edm.DELIMITER + name;
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmAnnotationElementImpl.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmAnnotationElementImpl.java b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmAnnotationElementImpl.java
new file mode 100644
index 0000000..ae117c1
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmAnnotationElementImpl.java
@@ -0,0 +1,93 @@
+/*******************************************************************************
+ * 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.client.core.edm.Impl;
+
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmAnnotationAttribute;
+import org.apache.olingo.odata2.api.edm.EdmAnnotationElement;
+
+/**
+ * Objects of this class represent AnnotationElement
+ *
+ */
+public class EdmAnnotationElementImpl implements EdmAnnotationElement {
+
+  List<EdmAnnotationElement> childElements;
+  List<EdmAnnotationAttribute> attributes; 
+  private String namespace;
+  private String prefix;
+  private String name;
+  private String text;
+
+  public void setNamespace(String namespace) {
+    this.namespace = namespace;
+  }
+  public void setPrefix(String prefix) {
+    this.prefix = prefix;
+  }
+  public void setName(String name) {
+    this.name = name;
+  }
+  public void setText(String text) {
+    this.text = text;
+  }
+ 
+  public void setChildElements(List<EdmAnnotationElement> childElements) {
+    this.childElements = childElements;
+  }
+  public void setAttributes(List<EdmAnnotationAttribute> attributes) {
+    this.attributes = attributes;
+  }
+  @Override
+  public String getName() {
+    return name;
+  }
+
+  @Override
+  public String getNamespace() {
+    return namespace;
+  }
+
+  @Override
+  public String getPrefix() {
+    return prefix;
+  }
+
+  @Override
+  public String getText() {
+    return text;
+  }
+
+  @Override
+  public List<EdmAnnotationElement> getChildElements() {
+    return childElements;
+  }
+
+  @Override
+  public List<EdmAnnotationAttribute> getAttributes() {
+    return attributes;
+  }
+  
+  @Override
+  public String toString() {
+    return namespace + Edm.DELIMITER + name;
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmAnnotationsImpl.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmAnnotationsImpl.java b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmAnnotationsImpl.java
new file mode 100644
index 0000000..95ac630
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmAnnotationsImpl.java
@@ -0,0 +1,82 @@
+/*******************************************************************************
+ * 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.client.core.edm.Impl;
+
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.EdmAnnotationAttribute;
+import org.apache.olingo.odata2.api.edm.EdmAnnotationElement;
+import org.apache.olingo.odata2.api.edm.EdmAnnotations;
+
+/**
+ * Objects of this class represent annotation elements and attributes
+ *
+ */
+public class EdmAnnotationsImpl implements EdmAnnotations {
+
+  private List<EdmAnnotationAttribute> annotationAttributes;
+  private List<EdmAnnotationElement> annotationElements;
+
+  @Override
+  public List<EdmAnnotationElement> getAnnotationElements() {
+    return annotationElements;
+  }
+
+  @Override
+  public EdmAnnotationElement getAnnotationElement(final String name, final String namespace) {
+    if (annotationElements != null) {
+      for (EdmAnnotationElement element : annotationElements) {
+        if (element.getName().equals(name) && element.getNamespace().equals(namespace)) {
+          return element;
+        }
+      }
+    }
+    return null;
+  }
+
+  @Override
+  public List<EdmAnnotationAttribute> getAnnotationAttributes() {
+    return annotationAttributes;
+  }
+
+  @Override
+  public EdmAnnotationAttribute getAnnotationAttribute(final String name, final String namespace) {
+    if (annotationAttributes != null) {
+      for (EdmAnnotationAttribute attribute : annotationAttributes) {
+        if (attribute.getName().equals(name) && attribute.getNamespace().equals(namespace)) {
+          return attribute;
+        }
+      }
+    }
+    return null;
+  }
+
+  public void setAnnotationAttributes(List<EdmAnnotationAttribute> annotationAttributes) {
+    this.annotationAttributes = annotationAttributes;
+  }
+
+  public void setAnnotationElements(List<EdmAnnotationElement> annotationElements) {
+    this.annotationElements = annotationElements;
+  }
+  @Override
+  public String toString() {
+      return String.format(annotationAttributes + " " +annotationElements);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmAssociationEndImpl.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmAssociationEndImpl.java b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmAssociationEndImpl.java
new file mode 100644
index 0000000..3f7a161
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmAssociationEndImpl.java
@@ -0,0 +1,106 @@
+/*******************************************************************************
+ * 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.client.core.edm.Impl;
+
+import org.apache.olingo.odata2.api.edm.EdmAnnotatable;
+import org.apache.olingo.odata2.api.edm.EdmAnnotations;
+import org.apache.olingo.odata2.api.edm.EdmEntityType;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
+import org.apache.olingo.odata2.api.edm.FullQualifiedName;
+import org.apache.olingo.odata2.client.core.edm.EdmMetadataAssociationEnd;
+import org.apache.olingo.odata2.client.core.edm.EdmOnDelete;
+
+/**
+ * Objects of this class represent AssociationEnds
+ *
+ */
+public class EdmAssociationEndImpl implements EdmMetadataAssociationEnd, EdmAnnotatable {
+
+  private EdmImpl edm;
+  private EdmAnnotations annotations;
+  private String role;
+  private EdmMultiplicity edmMultiplicity;
+  private FullQualifiedName associationEndTypeName;
+  private EdmOnDelete onDelete;
+
+  @Override
+  public String getRole() {
+    return role;
+  }
+
+  /**
+   * @param edm the edm to set
+   */
+  public void setEdm(EdmImpl edm) {
+    this.edm = edm;
+  }
+
+
+  @Override
+  public EdmEntityType getEntityType() throws EdmException {
+    EdmEntityType entityType = edm.getEntityType(
+        associationEndTypeName.getNamespace(), 
+       associationEndTypeName.getName());
+    if (entityType == null) {
+      throw new EdmException(EdmException.ENTITYTYPEPROBLEM);
+    }
+    return entityType;
+  }
+
+  @Override
+  public EdmMultiplicity getMultiplicity() {
+    return edmMultiplicity;
+  }
+
+  @Override
+  public EdmAnnotations getAnnotations() throws EdmException {
+    return annotations;
+  }
+
+  public void setRole(String role) {
+    this.role = role;
+  }
+
+  public void setMultiplicity(EdmMultiplicity edmMultiplicity) {
+    this.edmMultiplicity = edmMultiplicity;
+  }
+  
+  public void setType(FullQualifiedName associationEndTypeName) {
+    this.associationEndTypeName = associationEndTypeName;
+  }
+  
+  public void setAnnotations(EdmAnnotations annotations) {
+    this.annotations = annotations;
+  }
+
+  public void setOnDelete(EdmOnDelete onDelete) {
+    this.onDelete = onDelete;
+  }
+
+  @Override
+  public EdmOnDelete getOnDelete() {
+    return onDelete;
+  }
+
+  @Override
+  public String toString() {
+      return String.format(annotations.toString());
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmAssociationImpl.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmAssociationImpl.java b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmAssociationImpl.java
new file mode 100644
index 0000000..a885f94
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmAssociationImpl.java
@@ -0,0 +1,149 @@
+/*******************************************************************************
+ * 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.client.core.edm.Impl;
+
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmAnnotatable;
+import org.apache.olingo.odata2.api.edm.EdmAnnotations;
+import org.apache.olingo.odata2.api.edm.EdmAssociation;
+import org.apache.olingo.odata2.api.edm.EdmAssociationEnd;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
+import org.apache.olingo.odata2.api.edm.EdmReferentialConstraint;
+import org.apache.olingo.odata2.api.edm.EdmTypeKind;
+import org.apache.olingo.odata2.client.api.edm.EdmDocumentation;
+import org.apache.olingo.odata2.client.core.edm.EdmMetadataAssociationEnd;
+
+/**
+ * Objects of this class represent Asociation
+ *
+ */
+public class EdmAssociationImpl extends EdmNamedImpl implements EdmAssociation, EdmAnnotatable {
+
+  private String namespace;
+  private EdmAnnotations annotations;
+  private EdmReferentialConstraintImpl referentialConstraint;
+  private List<EdmMetadataAssociationEnd> associationEnds; 
+  private EdmDocumentation documentation;
+
+
+  public EdmDocumentation getDocumentation() {
+    return documentation;
+  }
+
+
+
+  public void setDocumentation(EdmDocumentation documentation) {
+    this.documentation = documentation;
+  }
+
+
+
+  public List<EdmMetadataAssociationEnd> getAssociationEnds() {
+    return associationEnds;
+  }
+
+
+  @Override
+  public String getNamespace() throws EdmException {
+    return namespace;
+  }
+  
+  
+
+  /**
+   * @param namespace the namespace to set
+   */
+  public void setNamespace(String namespace) {
+    this.namespace = namespace;
+  }
+
+  @Override
+  public EdmTypeKind getKind() {
+    return EdmTypeKind.ASSOCIATION;
+  }
+
+  @Override
+  public EdmAssociationEnd getEnd(final String role) throws EdmException {
+    if (!associationEnds.isEmpty()) {
+      EdmAssociationEnd end = associationEnds.get(0);
+      if (role.equals(end.getRole())) {
+        return end;
+      }
+      end = associationEnds.get(1);
+      if (role.equals(end.getRole())) {
+        return end;
+      }
+    }
+    return null;
+  }
+
+  @Override
+  public EdmAnnotations getAnnotations() throws EdmException {
+    return annotations;
+  }
+
+  public EdmMultiplicity getEndMultiplicity(final String role) throws EdmException {
+    EdmMetadataAssociationEnd end = getEnd1();
+    if (end!=null && role.equals(end.getRole())) {
+      return end.getMultiplicity();
+    }
+    end = getEnd2();
+    if (end!=null && role.equals(end.getRole())) {
+      return end.getMultiplicity();
+    }
+
+    return null;
+  }
+
+  @Override
+  public EdmMetadataAssociationEnd getEnd1() throws EdmException {
+    return associationEnds.isEmpty()?null:associationEnds.get(0);
+  }
+
+  @Override
+  public EdmMetadataAssociationEnd getEnd2() throws EdmException {
+    return  associationEnds.isEmpty()?null:associationEnds.get(1);
+  }
+
+  @Override
+  public EdmReferentialConstraint getReferentialConstraint() throws EdmException {
+    return this.referentialConstraint;
+  }
+
+  public void setReferentialConstraint(EdmReferentialConstraint referentialConstraint) {
+    this.referentialConstraint = (EdmReferentialConstraintImpl) referentialConstraint;
+  }
+
+  public void setAnnotations(EdmAnnotations annotations) {
+    this.annotations = annotations;
+  }
+
+  public void setAssociationEnds(List<EdmMetadataAssociationEnd> associationEnds) {
+    this.associationEnds = associationEnds;
+  } 
+  
+  @Override
+  public String toString() {
+    return namespace + Edm.DELIMITER + name;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmAssociationSetEndImpl.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmAssociationSetEndImpl.java b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmAssociationSetEndImpl.java
new file mode 100644
index 0000000..024c8ca
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmAssociationSetEndImpl.java
@@ -0,0 +1,92 @@
+/*******************************************************************************
+ * 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.client.core.edm.Impl;
+
+import org.apache.olingo.odata2.api.edm.EdmAnnotatable;
+import org.apache.olingo.odata2.api.edm.EdmAnnotations;
+import org.apache.olingo.odata2.api.edm.EdmAssociationSetEnd;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmException;
+
+/**
+ * Objects of this class represent AssociationSetEnd
+ *
+ */
+public class EdmAssociationSetEndImpl implements EdmAssociationSetEnd, EdmAnnotatable {
+
+  private EdmEntitySet entitySet;
+  private String role;
+  private EdmAssociationSetEnd end;
+  private EdmAnnotations annotations;
+  private String entitySetName;
+
+  @Override
+  public EdmEntitySet getEntitySet() throws EdmException {
+    return entitySet;
+  }
+
+  public EdmAssociationSetEnd getEnd() {
+    return end;
+  }
+
+  public void setEnd(EdmAssociationSetEnd end) {
+    this.end = end;
+  }
+  
+  public void setRole(String role) {
+    this.role = role;
+  }
+
+  public void setAnnotations(EdmAnnotations annotations) {
+    this.annotations = annotations;
+  }
+
+  @Override
+  public String getRole() {
+    return role;
+  }
+
+  @Override
+  public EdmAnnotations getAnnotations() throws EdmException {
+    return annotations;
+  }
+
+  public void setEntitySetName(String entitySetName) {
+    this.entitySetName = entitySetName;
+  }
+
+  /**
+   * @return the entitySetName
+   */
+  public String getEntitySetName() {
+    return entitySetName;
+  }
+
+  /**
+   * @param entitySet the entitySet to set
+   */
+  public void setEntitySet(EdmEntitySet entitySet) {
+    this.entitySet = entitySet;
+  }
+  
+  @Override
+  public String toString() {
+      return String.format(end.toString());
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmAssociationSetImpl.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmAssociationSetImpl.java b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmAssociationSetImpl.java
new file mode 100644
index 0000000..4df79b7
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmAssociationSetImpl.java
@@ -0,0 +1,137 @@
+/*******************************************************************************
+ * 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.client.core.edm.Impl;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmAnnotatable;
+import org.apache.olingo.odata2.api.edm.EdmAnnotations;
+import org.apache.olingo.odata2.api.edm.EdmAssociation;
+import org.apache.olingo.odata2.api.edm.EdmAssociationSet;
+import org.apache.olingo.odata2.api.edm.EdmAssociationSetEnd;
+import org.apache.olingo.odata2.api.edm.EdmEntityContainer;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.FullQualifiedName;
+import org.apache.olingo.odata2.client.api.edm.EdmDocumentation;
+
+/**
+ * Objects of this class represent AssociationSet
+ *
+ */
+public class EdmAssociationSetImpl extends EdmNamedImpl implements EdmAssociationSet, EdmAnnotatable {
+
+  private EdmEntityContainer edmEntityContainer;
+  private EdmAnnotations annotations;
+  private FullQualifiedName associationSetFQName;
+  private EdmAssociationSetEnd end2;
+  private EdmAssociationSetEnd end1;
+  private EdmDocumentation documentation;
+
+  
+  public FullQualifiedName getAssociationSetFQName() {
+    return associationSetFQName ;
+  }
+  public void setDocumentation(EdmDocumentation documentation) {
+    this.documentation = documentation;
+  }
+
+  @Override
+  public EdmAssociation getAssociation() throws EdmException {
+    EdmAssociation association =
+        edm.getAssociation(this.associationSetFQName.getNamespace(), 
+            this.associationSetFQName.getName());
+    if (association == null) {
+      throw new EdmException(EdmException.ASSOCIATIONNOTFOUND);
+    }
+    return association;
+  }
+
+  /**
+   * @param annotations the annotations to set
+   */
+  public void setAnnotations(EdmAnnotations annotations) {
+    this.annotations = annotations;
+  }
+
+  /**
+   * @param edmEntityContainer the edmEntityContainer to set
+   */
+  public void setEdmEntityContainer(EdmEntityContainer edmEntityContainer) {
+    this.edmEntityContainer = edmEntityContainer;
+  }
+
+  @Override
+  public EdmAssociationSetEnd getEnd(final String role) throws EdmException {
+    EdmAssociationSetEnd end;
+    if (end1.getRole().equals(role)) {
+      end = this.end1;
+    } else if (end2.getRole().equals(role)) {
+      end = this.end2;
+    } else {
+      return null;
+    }
+    EdmEntitySet entitySet = edmEntityContainer.getEntitySet(((EdmAssociationSetEndImpl)end).getEntitySetName());
+    if (entitySet == null) {
+      throw new EdmException(EdmException.COMMON);//TODO
+    }
+    return end;
+  }
+
+  @Override
+  public EdmEntityContainer getEntityContainer() throws EdmException {
+    return edmEntityContainer;
+  }
+
+  @Override
+  public EdmAnnotations getAnnotations() throws EdmException {
+    return annotations;
+  }
+
+  public void setAssociation(FullQualifiedName associationSetFQName) {
+    this.associationSetFQName = associationSetFQName;
+  }
+  
+  public void setEnd1(EdmAssociationSetEnd end1) {
+    this.end1 = end1;
+  }
+  
+  public void setEnd2(EdmAssociationSetEnd end2) {
+    this.end2 = end2;
+  }
+
+  /**
+   * @return the end2
+   */
+  public EdmAssociationSetEnd getEnd2() {
+    return end2;
+  }
+
+  /**
+   * @return the end1
+   */
+  public EdmAssociationSetEnd getEnd1() {
+    return end1;
+  }
+  
+  @Override
+  public String toString() {
+    return associationSetFQName.getNamespace() + Edm.DELIMITER + associationSetFQName.getName();
+  }
+  
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmComplexPropertyImpl.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmComplexPropertyImpl.java b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmComplexPropertyImpl.java
new file mode 100644
index 0000000..8d9692d
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmComplexPropertyImpl.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * 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.client.core.edm.Impl;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmType;
+
+/**
+ *  Objects of this class represent ComplexProperty
+ */
+public class EdmComplexPropertyImpl extends EdmPropertyImpl {
+
+
+
+  @Override
+  public EdmType getType() throws EdmException {
+    if (edmType == null) {
+      edmType = edm.getComplexType(typeName.getNamespace(), typeName.getName());
+    }
+    if (edmType == null) {
+      throw new EdmException(EdmException.TYPEPROBLEM);
+    }
+    return edmType;
+  }
+
+
+  public boolean isSimple() {
+    return false;
+  }
+  
+  @Override
+  public String toString() {
+    try {
+      return edmType.getNamespace()+ Edm.DELIMITER +  edmType.getName();
+    } catch (EdmException e) { //NOPMD  - suppressed
+      return null; //NOSONAR
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmComplexTypeImpl.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmComplexTypeImpl.java b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmComplexTypeImpl.java
new file mode 100644
index 0000000..3fc7c1a
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmComplexTypeImpl.java
@@ -0,0 +1,75 @@
+/*******************************************************************************
+ * 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.client.core.edm.Impl;
+
+import org.apache.olingo.odata2.api.edm.EdmComplexType;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmMapping;
+import org.apache.olingo.odata2.api.edm.EdmTypeKind;
+import org.apache.olingo.odata2.api.edm.FullQualifiedName;
+
+/**
+ * Objects of this class represent ComplexType
+ *
+ */
+public class EdmComplexTypeImpl extends EdmStructuralTypeImpl implements EdmComplexType{
+
+  private boolean isAbstract;
+
+  private FullQualifiedName baseType;
+  private EdmMapping mapping;
+  
+  public EdmMapping getMapping() {
+    return mapping;
+  }
+  public void setMapping(EdmMapping mapping) {
+    this.mapping = mapping;
+  }
+  public void setAbstract(boolean isAbstract) {
+    this.isAbstract = isAbstract;
+  }
+  @Override
+  public EdmComplexType getBaseType() throws EdmException {
+    if(edmBaseType!=null){
+      return (EdmComplexTypeImpl) edmBaseType;
+    } else {
+      return null;
+    }
+  }
+  public FullQualifiedName getEdmBaseTypeName() {
+    return baseType;
+  }
+  public void setBaseTypeName(FullQualifiedName baseType) {
+    this.baseType = baseType;
+  }
+  
+  public boolean isAbstract() {
+    return isAbstract;
+  }
+  
+  @Override
+  public String toString() {
+    return name;
+  }
+  
+  @Override
+  public EdmTypeKind getKind() {
+    return EdmTypeKind.COMPLEX;
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmCustomizableFeedMappingsImpl.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmCustomizableFeedMappingsImpl.java b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmCustomizableFeedMappingsImpl.java
new file mode 100644
index 0000000..180cb47
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmCustomizableFeedMappingsImpl.java
@@ -0,0 +1,140 @@
+/*******************************************************************************
+ * 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.client.core.edm.Impl;
+
+import org.apache.olingo.odata2.api.edm.EdmContentKind;
+import org.apache.olingo.odata2.api.edm.EdmCustomizableFeedMappings;
+
+/**
+ * Objects of this class represent customizable feed mappings.
+ * 
+ */
+public class EdmCustomizableFeedMappingsImpl implements EdmCustomizableFeedMappings {
+
+  private Boolean fcKeepInContent;
+  private EdmContentKind fcContentKind;
+  private String fcNsPrefix;
+  private String fcNsUri;
+  private String fcSourcePath;
+  private String fcTargetPath;
+
+  @Override
+  public Boolean isFcKeepInContent() {
+    return fcKeepInContent;
+  }
+
+  @Override
+  public EdmContentKind getFcContentKind() {
+    return fcContentKind;
+  }
+
+  @Override
+  public String getFcNsPrefix() {
+    return fcNsPrefix;
+  }
+
+  @Override
+  public String getFcNsUri() {
+    return fcNsUri;
+  }
+
+  @Override
+  public String getFcSourcePath() {
+    return fcSourcePath;
+  }
+
+  @Override
+  public String getFcTargetPath() {
+    return fcTargetPath;
+  }
+
+  /**
+   * @return <b>boolean</b>
+   */
+  public Boolean getFcKeepInContent() {
+    return fcKeepInContent;
+  }
+
+  /**
+   * Sets if this is kept in content.
+   * @param fcKeepInContent
+   * @return {@link EdmCustomizableFeedMappingsImpl} for method chaining
+   */
+  public EdmCustomizableFeedMappingsImpl setFcKeepInContent(final Boolean fcKeepInContent) {
+    this.fcKeepInContent = fcKeepInContent;
+    return this;
+  }
+
+  /**
+   * Sets the {@link EdmContentKind}.
+   * @param fcContentKind
+   * @return {@link EdmCustomizableFeedMappingsImpl} for method chaining
+   */
+  public EdmCustomizableFeedMappingsImpl setFcContentKind(final EdmContentKind fcContentKind) {
+    this.fcContentKind = fcContentKind;
+    return this;
+  }
+
+  /**
+   * Sets the prefix.
+   * @param fcNsPrefix
+   * @return {@link EdmCustomizableFeedMappingsImpl} for method chaining
+   */
+  public EdmCustomizableFeedMappingsImpl setFcNsPrefix(final String fcNsPrefix) {
+    this.fcNsPrefix = fcNsPrefix;
+    return this;
+  }
+
+  /**
+   * Sets the Uri.
+   * @param fcNsUri
+   * @return {@link EdmCustomizableFeedMappingsImpl} for method chaining
+   */
+  public EdmCustomizableFeedMappingsImpl setFcNsUri(final String fcNsUri) {
+    this.fcNsUri = fcNsUri;
+    return this;
+  }
+
+  /**
+   * Sets the source path.
+   * @param fcSourcePath
+   * @return {@link EdmCustomizableFeedMappingsImpl} for method chaining
+   */
+  public EdmCustomizableFeedMappingsImpl setFcSourcePath(final String fcSourcePath) {
+    this.fcSourcePath = fcSourcePath;
+    return this;
+  }
+
+  /**
+   * <p>Sets the target path.</p>
+   * <p>For standard Atom elements, constants are available in {@link org.apache.olingo.odata2.api.edm.EdmTargetPath
+   * EdmTargetPath}.</p>
+   * @param fcTargetPath
+   * @return {@link EdmCustomizableFeedMappingsImpl} for method chaining
+   */
+  public EdmCustomizableFeedMappingsImpl setFcTargetPath(final String fcTargetPath) {
+    this.fcTargetPath = fcTargetPath;
+    return this;
+  }
+  
+  @Override
+  public String toString() {
+      return String.format(fcNsPrefix + " " + fcNsUri);
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmDocumentationImpl.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmDocumentationImpl.java b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmDocumentationImpl.java
new file mode 100644
index 0000000..f65c4ba
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmDocumentationImpl.java
@@ -0,0 +1,110 @@
+/*******************************************************************************
+ * 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.client.core.edm.Impl;
+
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.EdmAnnotationAttribute;
+import org.apache.olingo.odata2.api.edm.EdmAnnotationElement;
+import org.apache.olingo.odata2.client.api.edm.EdmDocumentation;
+
+/**
+ * Objects of this class represent documentation
+ * 
+ */
+public class EdmDocumentationImpl implements EdmDocumentation{
+
+  private String summary;
+  private String longDescription;
+  private List<EdmAnnotationAttribute> annotationAttributes;
+  private List<EdmAnnotationElement> annotationElements;
+
+  /**
+   * @return <b>String</b> summary
+   */
+  public String getSummary() {
+    return summary;
+  }
+
+  /**
+   * @return <b>String</b> the long description
+   */
+  public String getLongDescription() {
+    return longDescription;
+  }
+
+  /**
+   * @return collection of {@link EdmAnnotationAttributeImpl} annotation attributes
+   */
+  public List<EdmAnnotationAttribute> getAnnotationAttributes() {
+    return annotationAttributes;
+  }
+
+  /**
+   * @return collection of {@link AnnotationElement} annotation elements
+   */
+  public List<EdmAnnotationElement> getAnnotationElements() {
+    return annotationElements;
+  }
+
+  /**
+   * Sets the summary for this {@link EdmDocumentationImpl}
+   * @param summary
+   * @return {@link EdmDocumentationImpl} for method chaining
+   */
+  public EdmDocumentationImpl setSummary(final String summary) {
+    this.summary = summary;
+    return this;
+  }
+
+  /**
+   * Sets the long description for this {@link EdmDocumentationImpl}
+   * @param longDescription
+   * @return {@link EdmDocumentationImpl} for method chaining
+   */
+  public EdmDocumentationImpl setLongDescription(final String longDescription) {
+    this.longDescription = longDescription;
+    return this;
+  }
+
+  /**
+   * Sets the collection of {@link EdmAnnotationAttributeImpl} for this {@link EdmDocumentationImpl}
+   * @param annotationAttributes
+   * @return {@link EdmDocumentationImpl} for method chaining
+   */
+  public EdmDocumentationImpl setAnnotationAttributes(final List<EdmAnnotationAttribute> annotationAttributes) {
+    this.annotationAttributes = annotationAttributes;
+    return this;
+  }
+
+  /**
+   * Sets the collection of {@link AnnotationElement} for this {@link EdmDocumentationImpl}
+   * @param annotationElements
+   * @return {@link EdmDocumentationImpl} for method chaining
+   */
+  public EdmDocumentationImpl setAnnotationElements(final List<EdmAnnotationElement> annotationElements) {
+    this.annotationElements = annotationElements;
+    return this;
+  }
+  
+  @Override
+  public String toString() {
+      return String.format(summary);
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmElementImpl.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmElementImpl.java b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmElementImpl.java
new file mode 100644
index 0000000..480af98
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmElementImpl.java
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * 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.client.core.edm.Impl;
+
+import org.apache.olingo.odata2.api.edm.EdmElement;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmFacets;
+import org.apache.olingo.odata2.api.edm.EdmMapping;
+
+/**
+ *  Objects of this class represent EdmElement
+ */
+public abstract class EdmElementImpl extends EdmTypedImpl implements EdmElement {
+
+  private EdmFacets edmFacets;
+  private EdmMapping edmMapping;
+
+  @Override
+  public EdmMapping getMapping() throws EdmException {
+    return edmMapping;
+  }
+
+  public void setFacets(EdmFacets edmFacets) {
+    this.edmFacets = edmFacets;
+  }
+
+  public void setMapping(EdmMapping edmMapping) {
+    this.edmMapping = edmMapping;
+  }
+
+  @Override
+  public EdmFacets getFacets() throws EdmException {
+    return edmFacets;
+  }  
+  @Override
+  public String toString() {
+      return String.format(name);
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmEntityContainerImpl.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmEntityContainerImpl.java b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmEntityContainerImpl.java
new file mode 100644
index 0000000..bed4d44
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmEntityContainerImpl.java
@@ -0,0 +1,222 @@
+/*******************************************************************************
+ * 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.client.core.edm.Impl;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.apache.olingo.odata2.api.edm.EdmAnnotatable;
+import org.apache.olingo.odata2.api.edm.EdmAnnotations;
+import org.apache.olingo.odata2.api.edm.EdmAssociation;
+import org.apache.olingo.odata2.api.edm.EdmAssociationSet;
+import org.apache.olingo.odata2.api.edm.EdmEntityContainer;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmFunctionImport;
+import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.client.api.edm.ClientEdm;
+import org.apache.olingo.odata2.client.api.edm.EdmDocumentation;
+
+/**
+ *  Objects of this class represent EdmEntityContainer
+ */
+public class EdmEntityContainerImpl implements EdmEntityContainer, EdmAnnotatable {
+
+  private EdmImpl edm;
+  private List<EdmEntityContainer> entityContainerHierachy;
+  private List<EdmEntitySet> edmEntitySets;
+  private Map<String, EdmAssociationSet> edmAssociationSetMap;
+  private List<EdmAssociationSet> edmAssociationSets;
+  private List<EdmFunctionImport> edmFunctionImports;
+  private EdmEntityContainer edmExtendedEntityContainer;
+  private boolean isDefaultContainer;
+  private EdmAnnotations annotations;
+  private EdmDocumentation documentation;
+  private String name;
+  private String extendz;
+
+  public Map<String, EdmAssociationSet> getEdmAssociationSetMap() {
+    return edmAssociationSetMap;
+  }
+
+  public void setEdmAssociationSetMap(Map<String, EdmAssociationSet> associationSetMap) {
+    this.edmAssociationSetMap = associationSetMap;
+  }
+
+  public EdmDocumentation getDocumentation() {
+    return documentation;
+  }
+
+  public void setDocumentation(EdmDocumentation documentation) {
+    this.documentation = documentation;
+  }
+
+  public void setEdm(EdmImpl edm) {
+    this.edm = edm;
+  }
+
+  public ClientEdm getEdm() {
+    return edm;
+  }
+
+  public EdmEntityContainer getEdmExtendedEntityContainer() {
+    return edmExtendedEntityContainer;
+  }
+
+  public void setEdmExtendedEntityContainer(EdmEntityContainer edmExtendedEntityContainer) {
+    this.edmExtendedEntityContainer = edmExtendedEntityContainer;
+  }
+
+  public void setEntityContainerHierachy(List<EdmEntityContainer> entityContainerHierachy) {
+    this.entityContainerHierachy = entityContainerHierachy;
+  }
+
+  public String getExtendz() {
+    return extendz;
+  }
+
+  public void setExtendz(String extendz) {
+    this.extendz = extendz;
+  }
+
+  public void setName(String name) {
+    this.name = name;
+  }
+
+  public void setAnnotations(EdmAnnotations annotations) {
+    this.annotations = annotations;
+  }
+  public EdmEntityContainerImpl(final EdmImpl edm)
+      throws EdmException {
+    this.edm = edm;
+    edmEntitySets = new ArrayList<EdmEntitySet>();
+    edmAssociationSets = new ArrayList<EdmAssociationSet>();
+    edmFunctionImports = new ArrayList<EdmFunctionImport>();
+  }
+
+  public boolean isDefaultContainer() {
+    return isDefaultContainer;
+  }
+
+  public void setDefaultContainer(boolean isDefaultContainer) {
+    this.isDefaultContainer = isDefaultContainer;
+  }
+  @Override
+  public String getName() throws EdmException {
+    return name;
+  }
+
+  @Override
+  public EdmEntitySet getEntitySet(final String name) throws EdmException {
+    EdmEntitySet edmEntitySet = null;
+      for(EdmEntitySet entity:edmEntitySets){
+        if(name.equals(entity.getName())){
+          edmEntitySet = entity;
+                
+      }
+    }
+    return edmEntitySet;
+   
+  }
+
+  @Override
+  public EdmFunctionImport getFunctionImport(final String name) throws EdmException {
+    for (EdmFunctionImport edmFunctionImport : edmFunctionImports) {
+      if (edmFunctionImport.getName().equalsIgnoreCase(name)) {
+        return edmFunctionImport;
+      }
+    }
+    return null;
+  }
+
+  @Override
+  public EdmAssociationSet getAssociationSet(final EdmEntitySet sourceEntitySet,
+      final EdmNavigationProperty navigationProperty) throws EdmException {
+    EdmAssociation edmAssociation = navigationProperty.getRelationship();
+    String association = edmAssociation.getNamespace() + "." + edmAssociation.getName();
+    String entitySetName = sourceEntitySet.getName();
+    String entitySetFromRole = navigationProperty.getFromRole();
+
+    String key = entitySetName + ">>" + association + ">>" + entitySetFromRole;
+
+    for (Entry<String, EdmAssociationSet> edmAssociationSet : edmAssociationSetMap.entrySet()) {
+      if (edmAssociationSet.getKey().equalsIgnoreCase(key)) {
+        return edmAssociationSet.getValue();
+      }
+    }
+   return null;
+
+  }
+
+  @Override
+  public boolean isDefaultEntityContainer() {
+    return isDefaultContainer;
+  }
+
+  @Override
+  public EdmAnnotations getAnnotations() throws EdmException {
+    return annotations;
+  }
+
+  @Override
+  public List<EdmEntitySet> getEntitySets() throws EdmException {
+    return edmEntitySets;
+  }
+
+ 
+
+  @Override
+  public List<EdmAssociationSet> getAssociationSets() throws EdmException {
+    return edmAssociationSets;
+  }
+
+  public  List<EdmEntitySet> getEdmEntitySets() {
+    return edmEntitySets;
+  }
+
+  public EdmEntityContainerImpl setEdmEntitySets( List<EdmEntitySet> edmEntitySets) {
+    this.edmEntitySets = edmEntitySets;
+    return this;
+  }
+
+  public List<EdmAssociationSet> getEdmAssociationSets() {
+    return edmAssociationSets;
+  }
+
+  public EdmEntityContainerImpl setEdmAssociationSets(List<EdmAssociationSet> edmAssociationSets) {
+    this.edmAssociationSets = edmAssociationSets;
+    return this;
+  }
+
+  public List<EdmFunctionImport> getEdmFunctionImports() {
+    return edmFunctionImports;
+  }
+
+  public EdmEntityContainerImpl setEdmFunctionImports(List<EdmFunctionImport> edmFunctionImports) {
+    this.edmFunctionImports = edmFunctionImports;
+    return this;
+  }  
+  @Override
+  public String toString() {
+      return String.format(name);
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmEntitySetImpl.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmEntitySetImpl.java b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmEntitySetImpl.java
new file mode 100644
index 0000000..103ab0a
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmEntitySetImpl.java
@@ -0,0 +1,136 @@
+/*******************************************************************************
+ * 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.client.core.edm.Impl;
+
+import org.apache.olingo.odata2.api.edm.EdmAnnotatable;
+import org.apache.olingo.odata2.api.edm.EdmAnnotations;
+import org.apache.olingo.odata2.api.edm.EdmAssociationSet;
+import org.apache.olingo.odata2.api.edm.EdmAssociationSetEnd;
+import org.apache.olingo.odata2.api.edm.EdmEntityContainer;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmEntityType;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmMapping;
+import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
+import org.apache.olingo.odata2.api.edm.FullQualifiedName;
+import org.apache.olingo.odata2.client.api.edm.EdmDocumentation;
+
+/**
+ * Objects of this class represent EdmEntitySet
+ *
+ */
+public class EdmEntitySetImpl extends EdmNamedImpl implements EdmEntitySet, EdmAnnotatable {
+
+  private EdmEntityContainer edmEntityContainer;
+  private EdmEntityType edmEntityType;  
+  private EdmAnnotationsImpl annotations;
+  private FullQualifiedName entityTypeName;
+  
+  private EdmMapping mapping;
+  private EdmDocumentation documentation;  
+
+ 
+  public FullQualifiedName getEntityTypeName() {
+    return entityTypeName;
+  }
+
+  public void setEntityTypeName(FullQualifiedName entityTypeName) {
+    this.entityTypeName = entityTypeName;
+  }
+
+  @Override
+  public EdmEntityType getEntityType() throws EdmException {
+    return edmEntityType;
+  }
+  
+  public EdmEntityContainer getEdmEntityContainer() {
+    return edmEntityContainer;
+  }
+
+  public void setEdmEntityContainer(EdmEntityContainer edmEntityContainer) {
+    this.edmEntityContainer = edmEntityContainer;
+  }
+
+  public EdmEntityType getEdmEntityType() {
+    return edmEntityType;
+  }
+
+  public void setEdmEntityType(EdmEntityType edmEntityType) {
+    this.edmEntityType = edmEntityType;
+  }
+
+  public void setAnnotations(EdmAnnotationsImpl annotations) {
+    this.annotations = annotations;
+  }
+
+  public EdmDocumentation getDocumentation() {
+    return documentation;
+  }
+
+  public void setDocumentation(EdmDocumentation documentation) {
+    this.documentation = documentation;
+  }
+
+  public void setMapping(EdmMapping mapping) {
+    this.mapping = mapping;
+  }
+
+  @Override
+  public EdmEntitySet getRelatedEntitySet(final EdmNavigationProperty navigationProperty) throws EdmException {
+    EdmAssociationSet associationSet =
+        edmEntityContainer.getAssociationSet(edmEntityContainer.getEntitySet(name), navigationProperty);
+    if(associationSet == null){
+      return null;
+    }
+    EdmAssociationSetEnd toEnd = associationSet.getEnd(navigationProperty.getToRole());
+    if (toEnd == null) {
+      throw new EdmException(EdmException.NAVIGATIONPROPERTYNOTFOUND,navigationProperty.getName());
+    }
+    EdmEntitySet targetEntitySet = toEnd.getEntitySet();
+    if (targetEntitySet == null) {
+      throw new EdmException(EdmException.NAVIGATIONPROPERTYNOTFOUND,navigationProperty.getName());
+    }
+    return targetEntitySet;
+  }
+
+  @Override
+  public EdmEntityContainer getEntityContainer() throws EdmException {
+    return edmEntityContainer;
+  }
+
+  @Override
+  public EdmAnnotations getAnnotations() throws EdmException {
+    return annotations;
+  }
+
+  @Override
+  public EdmMapping getMapping() throws EdmException {
+    return mapping;
+  }
+
+  public void setEdmEntityTypeName(FullQualifiedName fqName) {
+    this.entityTypeName = fqName;    
+  }
+  
+  @Override
+  public String toString() {
+      return String.format(name);
+  }
+  
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmEntityTypeImpl.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmEntityTypeImpl.java b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmEntityTypeImpl.java
new file mode 100644
index 0000000..d4f1032
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmEntityTypeImpl.java
@@ -0,0 +1,133 @@
+/*******************************************************************************
+ * 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.client.core.edm.Impl;
+
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmCustomizableFeedMappings;
+import org.apache.olingo.odata2.api.edm.EdmEntityType;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.edm.EdmTyped;
+import org.apache.olingo.odata2.api.edm.FullQualifiedName;
+
+/**
+ * Objects of this class represent EdmEntityType
+ *
+ */
+public class EdmEntityTypeImpl extends EdmStructuralTypeImpl implements EdmEntityType {
+
+  private List<EdmProperty> edmKeyProperties;
+  private List<String> edmKeyPropertyNames;
+  private List<EdmNavigationProperty> navigationProperties;
+  private List<String> edmNavigationPropertyNames;
+  private boolean hasStream;
+  private boolean isAbstract;
+  private FullQualifiedName baseType;
+  private EdmCustomizableFeedMappings customizableFeedMappings;
+
+  public void setBaseType(FullQualifiedName baseType) {
+    this.baseType = baseType;
+  }
+
+  public void setAbstract(boolean isAbstract) {
+    this.isAbstract = isAbstract;
+  }
+
+   public void setEdmKeyProperties(List<EdmProperty> edmKeyProperties) {
+    this.edmKeyProperties = edmKeyProperties;
+  }
+
+  public void setNavigationProperties(List<EdmNavigationProperty> navigationProperties) {
+    this.navigationProperties = navigationProperties;
+  }
+
+  public void setEdmNavigationPropertyNames(List<String> edmNavigationPropertyNames) {
+    this.edmNavigationPropertyNames = edmNavigationPropertyNames;
+  }
+
+  public void setHasStream(boolean hasStream) {
+    this.hasStream = hasStream;
+  }
+
+  @Override
+  public List<String> getKeyPropertyNames() throws EdmException {
+    return edmKeyPropertyNames;
+  }
+
+  public void setEdmKeyPropertyNames(List<String> edmKeyPropertyNames) {
+    this.edmKeyPropertyNames = edmKeyPropertyNames;
+  }
+
+  @Override
+  public List<EdmProperty> getKeyProperties() throws EdmException {
+    return edmKeyProperties;
+  }
+
+  @Override
+  public boolean hasStream() throws EdmException {
+    return hasStream;
+  }
+
+  @Override
+  public EdmCustomizableFeedMappings getCustomizableFeedMappings() throws EdmException {
+    return customizableFeedMappings;
+  }
+
+  @Override
+  public List<String> getNavigationPropertyNames() throws EdmException {
+    return edmNavigationPropertyNames;
+  }
+
+  @Override
+  public EdmEntityType getBaseType() throws EdmException {
+    return (EdmEntityType) edmBaseType;
+  }
+
+  public FullQualifiedName getBaseTypeName() throws EdmException {
+    return baseType;
+  }
+
+  @Override
+  protected EdmTyped getPropertyInternal(final String name) throws EdmException {
+    EdmTyped edmProperty = super.getPropertyInternal(name);
+
+    if (edmProperty != null) {
+      return edmProperty;
+    }
+    for (EdmNavigationProperty navigations : navigationProperties) {
+      if (navigations.getName().equals(name)) {
+        return navigations;
+      }
+    }
+    return edmProperty;
+  }
+
+  public void setCustomizableFeedMappings(EdmCustomizableFeedMappings edmCustomizableFeedMappings) {
+    this.customizableFeedMappings = edmCustomizableFeedMappings;
+  }
+  
+  @Override
+  public String toString() {
+      return String.format(namespace+ Edm.DELIMITER +name);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmFunctionImportImpl.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmFunctionImportImpl.java b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmFunctionImportImpl.java
new file mode 100644
index 0000000..8521ad7
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmFunctionImportImpl.java
@@ -0,0 +1,179 @@
+/*******************************************************************************
+ * 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.client.core.edm.Impl;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.apache.olingo.odata2.api.edm.EdmAnnotatable;
+import org.apache.olingo.odata2.api.edm.EdmAnnotations;
+import org.apache.olingo.odata2.api.edm.EdmEntityContainer;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmFunctionImport;
+import org.apache.olingo.odata2.api.edm.EdmMapping;
+import org.apache.olingo.odata2.api.edm.EdmParameter;
+import org.apache.olingo.odata2.api.edm.EdmTyped;
+import org.apache.olingo.odata2.client.api.edm.EdmDocumentation;
+
+/**
+ *  Objects of this class represent EdmFunctionImport
+ */
+public class EdmFunctionImportImpl extends EdmNamedImpl implements EdmFunctionImport, EdmAnnotatable {
+
+  private EdmEntityContainer edmEntityContainer;
+  private Map<String, EdmParameter> edmParameters;
+  private Map<String, ArrayList<EdmFunctionImportParameter>> parameters;
+  private List<String> parametersList;
+  private EdmAnnotations annotations;
+  private EdmTyped edmReturnType;
+  private String entitySet;
+  private String httpMethod;
+  private EdmMapping mapping;
+  private EdmDocumentation documentation;
+
+  public EdmTyped getEdmReturnType() {
+    return edmReturnType;
+  }
+
+  public void setEdmReturnType(EdmTyped edmReturnType) {
+    this.edmReturnType = edmReturnType;
+  }
+
+  public EdmDocumentation getDocumentation() {
+    return documentation;
+  }
+
+  public void setDocumentation(EdmDocumentation documentation) {
+    this.documentation = documentation;
+  }
+
+  public void setMapping(EdmMapping mapping) {
+    this.mapping = mapping;
+  }
+
+  /**
+   * @param returnType the returnType to set
+   */
+  public void setReturnType(EdmTyped returnType) {
+    this.edmReturnType = returnType;
+  }
+
+  /**
+   * @param edmEntitySet the entitySet to set
+   */
+  public void setEntitySet(String edmEntitySet) {
+    this.entitySet = edmEntitySet;
+  }
+
+  /**
+   * @param httpMethod the httpMethod to set
+   */
+  public void setHttpMethod(String httpMethod) {
+    this.httpMethod = httpMethod;
+  }
+
+  public EdmEntityContainer getEdmEntityContainer() {
+    return edmEntityContainer;
+  }
+
+  public void setEdmEntityContainer(EdmEntityContainer edmEntityContainer) {
+    this.edmEntityContainer = edmEntityContainer;
+  }
+
+  public Map<String, EdmParameter> getEdmParameters() {
+    return edmParameters;
+  }
+
+  public void setEdmParameters(Map<String, EdmParameter> edmParameters) {
+    this.edmParameters = edmParameters;
+  }
+
+  public Map<String, ArrayList<EdmFunctionImportParameter>> getParameters() {
+    return parameters;
+  }
+
+  public void setParameters(Map<String, ArrayList<EdmFunctionImportParameter>> parameters) {
+    this.parameters = parameters;
+  }
+
+  public List<String> getParametersList() {
+    return parametersList;
+  }
+
+  public void setParametersList(List<String> parametersList) {
+    this.parametersList = parametersList;
+  }
+
+  public void setAnnotations(EdmAnnotations annotations) {
+    this.annotations = annotations;
+  }
+
+  @Override
+  public EdmParameter getParameter(final String name) throws EdmException {
+    for (Entry<String, EdmParameter> param : edmParameters.entrySet()) {
+      if (param.getKey().equalsIgnoreCase(name)) {
+        return param.getValue();
+      }
+    }
+    return null;
+  }
+
+  @Override
+  public List<String> getParameterNames() throws EdmException {
+    return parametersList;
+  }
+
+  @Override
+  public EdmEntitySet getEntitySet() throws EdmException {
+    return edmEntityContainer.getEntitySet(entitySet);
+  }
+
+  @Override
+  public String getHttpMethod() throws EdmException {
+    return this.httpMethod;
+  }
+
+  @Override
+  public EdmTyped getReturnType() throws EdmException {
+    return edmReturnType;
+  }
+
+  @Override
+  public EdmEntityContainer getEntityContainer() throws EdmException {
+    return edmEntityContainer;
+  }
+
+  @Override
+  public EdmAnnotations getAnnotations() throws EdmException {
+    return annotations;
+  }
+
+  @Override
+  public EdmMapping getMapping() throws EdmException {
+    return mapping;
+  }  
+  @Override
+  public String toString() {
+    return String.format(name);
+  }
+
+}


[15/24] olingo-odata2 git commit: [OLINGO-1253]Client Module for Olingo v2

Posted by ar...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/deserializer/JsonEntryDeserializerTest.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/deserializer/JsonEntryDeserializerTest.java b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/deserializer/JsonEntryDeserializerTest.java
new file mode 100644
index 0000000..ac8d934
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/deserializer/JsonEntryDeserializerTest.java
@@ -0,0 +1,539 @@
+/*******************************************************************************
+ * 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.client.core.ep.deserializer;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.InputStream;
+import java.util.Calendar;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.TimeZone;
+
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+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.ODataFeed;
+import org.apache.olingo.odata2.api.uri.ExpandSelectTreeNode;
+import org.apache.olingo.odata2.client.api.ep.DeserializerProperties;
+import org.apache.olingo.odata2.client.api.ep.EntityStream;
+import org.apache.olingo.odata2.testutil.mock.MockFacade;
+import org.junit.Test;
+
+/**
+ *  
+ */
+public class JsonEntryDeserializerTest extends AbstractDeserializerTest {
+
+  private static final String SIMPLE_ENTRY_BUILDING = "JsonBuilding.json";
+  private static final String SIMPLE_ENTRY_ROOM = "JsonRoom.json";
+  private static final String SIMPLE_ENTRY_EMPLOYEE = "JsonEmployee.json";
+  private static final String SIMPLE_ENTRY_TEAM = "JsonTeam.json";
+  private static final String INVALID_ENTRY_TEAM_DOUBLE_NAME_PROPERTY = "JsonInvalidTeamDoubleNameProperty.json";
+  private static final String SIMPLE_ENTRY_BUILDING_WITHOUT_D = "JsonBuildingWithoutD.json";
+
+  // Negative Test jsonStart
+  private static final String negativeJsonStart_1 = "{ \"abc\": {";
+  private static final String negativeJsonStart_2 = "{ \"d\": [a: 1, b: 2] }";
+
+  @Test
+  public void readContentOnlyEmployee() throws Exception {
+    // prepare
+    String content = readFile("JsonEmployeeContentOnly.json");
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+    InputStream contentBody = createContentAsStream(content);
+    EntityStream contentStream = new EntityStream();
+    contentStream.setContent(contentBody);
+    contentStream.setReadProperties(DeserializerProperties.init().build());
+
+    // execute
+    JsonEntityDeserializer xec = new JsonEntityDeserializer();
+    ODataEntry result =
+        xec.readEntry(entitySet, contentStream);
+
+    // verify
+    assertEquals(9, result.getProperties().size());
+  }
+
+  @Test
+  public void readContentOnlyRoom() throws Exception {
+    // prepare
+    String content = readFile("JsonRoomContentOnly.json");
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+    InputStream contentBody = createContentAsStream(content);
+    EntityStream entityStream = new EntityStream();
+    entityStream.setContent(contentBody);
+    entityStream.setReadProperties(DeserializerProperties.init().build());
+
+    // execute
+    JsonEntityDeserializer xec = new JsonEntityDeserializer();
+    ODataEntry result =
+        xec.readEntry(entitySet, entityStream);
+
+    // verify
+    assertEquals(4, result.getProperties().size());
+  }
+
+  @Test
+  public void readContentOnlyEmployeeWithAdditionalLink() throws Exception {
+    // prepare
+    String content = readFile("JsonEmployeeContentOnlyWithAdditionalLink.json");
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+    InputStream contentBody = createContentAsStream(content);
+    EntityStream entityStream = new EntityStream();
+    entityStream.setContent(contentBody);
+    entityStream.setReadProperties(DeserializerProperties.init().build());
+
+    // execute
+    JsonEntityDeserializer xec = new JsonEntityDeserializer();
+    ODataEntry result =
+        xec.readEntry(entitySet, entityStream);
+
+    // verify
+    assertEquals(9, result.getProperties().size());
+    List<String> associationUris = result.getMetadata().getAssociationUris("ne_Manager");
+    assertEquals(1, associationUris.size());
+    assertEquals("http://host:8080/ReferenceScenario.svc/Managers('1')", associationUris.get(0));
+  }
+
+  @Test
+  public void readContentOnlyRoomWithAdditionalLink() throws Exception {
+    // prepare
+    String content = readFile("JsonRoomContentOnlyWithAdditionalLink.json");
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+    InputStream contentBody = createContentAsStream(content);
+    EntityStream entityStream = new EntityStream();
+    entityStream.setContent(contentBody);
+    entityStream.setReadProperties(DeserializerProperties.init().build());
+
+    // execute
+    JsonEntityDeserializer xec = new JsonEntityDeserializer();
+    ODataEntry result =
+        xec.readEntry(entitySet, entityStream);
+
+    // verify
+    assertEquals(4, result.getProperties().size());
+    List<String> associationUris = result.getMetadata().getAssociationUris("nr_Building");
+    assertEquals(1, associationUris.size());
+    assertEquals("http://host:8080/ReferenceScenario.svc/Buildings('1')", associationUris.get(0));
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void doubleClosingBracketsAtTheEnd() throws Exception {
+    String invalidJson = "{ \"Id\" : \"1\", \"Seats\" : 1, \"Version\" : 1}}";
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+    InputStream contentBody = createContentAsStream(invalidJson);
+    EntityStream entityStream = new EntityStream();
+    entityStream.setContent(contentBody);
+    entityStream.setReadProperties(DEFAULT_PROPERTIES);
+
+    // execute
+    JsonEntityDeserializer xec = new JsonEntityDeserializer();
+    xec.readEntry(entitySet, entityStream);
+  }
+
+  @Test
+  public void readSimpleRoomEntry() throws Exception {
+    ODataEntry roomEntry = prepareAndExecuteEntry(SIMPLE_ENTRY_ROOM, "Rooms", DEFAULT_PROPERTIES);
+
+    // verify
+    Map<String, Object> properties = roomEntry.getProperties();
+    assertEquals(4, properties.size());
+
+    assertEquals("1", properties.get("Id"));
+    assertEquals("Room 1", properties.get("Name"));
+    assertEquals((short) 1, properties.get("Seats"));
+    assertEquals((short) 1, properties.get("Version"));
+
+    List<String> associationUris = roomEntry.getMetadata().getAssociationUris("nr_Employees");
+    assertEquals(1, associationUris.size());
+    assertEquals("http://localhost:8080/ReferenceScenario.svc/Rooms('1')/nr_Employees", associationUris.get(0));
+
+    associationUris = roomEntry.getMetadata().getAssociationUris("nr_Building");
+    assertEquals(1, associationUris.size());
+    assertEquals("http://localhost:8080/ReferenceScenario.svc/Rooms('1')/nr_Building", associationUris.get(0));
+
+    EntryMetadata metadata = roomEntry.getMetadata();
+    assertEquals("W/\"1\"", metadata.getEtag());
+  }
+
+  @SuppressWarnings("unchecked")
+  @Test
+  public void readSimpleEmployeeEntry() throws Exception {
+    ODataEntry result = prepareAndExecuteEntry(SIMPLE_ENTRY_EMPLOYEE, "Employees", DEFAULT_PROPERTIES);
+
+    // 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("Employees('1')/$value", properties.get("ImageUrl"));
+
+    List<String> associationUris = result.getMetadata().getAssociationUris("ne_Manager");
+    assertEquals(1, associationUris.size());
+    assertEquals("http://localhost:8080/ReferenceScenario.svc/Employees('1')/ne_Manager", associationUris.get(0));
+
+    associationUris = result.getMetadata().getAssociationUris("ne_Team");
+    assertEquals(1, associationUris.size());
+    assertEquals("http://localhost:8080/ReferenceScenario.svc/Employees('1')/ne_Team", associationUris.get(0));
+
+    associationUris = result.getMetadata().getAssociationUris("ne_Room");
+    assertEquals(1, associationUris.size());
+    assertEquals("http://localhost:8080/ReferenceScenario.svc/Employees('1')/ne_Room", associationUris.get(0));
+
+    MediaMetadata mediaMetadata = result.getMediaMetadata();
+    assertEquals("image/jpeg", mediaMetadata.getContentType());
+    assertEquals("http://localhost:8080/ReferenceScenario.svc/Employees('1')/$value", mediaMetadata.getEditLink());
+    assertEquals("Employees('1')/$value", mediaMetadata.getSourceLink());
+    assertNull(mediaMetadata.getEtag());
+  }
+
+  @Test
+  public void readSimpleTeamEntry() throws Exception {
+    ODataEntry result = prepareAndExecuteEntry(SIMPLE_ENTRY_TEAM, "Teams", DEFAULT_PROPERTIES);
+
+    Map<String, Object> properties = result.getProperties();
+    assertNotNull(properties);
+    assertEquals("1", properties.get("Id"));
+    assertEquals("Team 1", properties.get("Name"));
+    assertEquals(Boolean.FALSE, properties.get("isScrumTeam"));
+    assertNull(properties.get("nt_Employees"));
+
+    List<String> associationUris = result.getMetadata().getAssociationUris("nt_Employees");
+    assertEquals(1, associationUris.size());
+    assertEquals("http://localhost:8080/ReferenceScenario.svc/Teams('1')/nt_Employees", associationUris.get(0));
+
+    checkMediaDataInitial(result.getMediaMetadata());
+  }
+
+  @Test
+  public void readSimpleBuildingEntry() throws Exception {
+    ODataEntry result = prepareAndExecuteEntry(SIMPLE_ENTRY_BUILDING, "Buildings", DEFAULT_PROPERTIES);
+    // verify
+    Map<String, Object> properties = result.getProperties();
+    assertNotNull(properties);
+    assertEquals("1", properties.get("Id"));
+    assertEquals("Building 1", properties.get("Name"));
+    assertNull(properties.get("Image"));
+    assertNull(properties.get("nb_Rooms"));
+
+    List<String> associationUris = result.getMetadata().getAssociationUris("nb_Rooms");
+    assertEquals(1, associationUris.size());
+    assertEquals("http://localhost:8080/ReferenceScenario.svc/Buildings('1')/nb_Rooms", associationUris.get(0));
+
+    checkMediaDataInitial(result.getMediaMetadata());
+  }
+
+  @Test
+  public void readSimpleBuildingEntryWithoutD() throws Exception {
+    ODataEntry result = prepareAndExecuteEntry(SIMPLE_ENTRY_BUILDING_WITHOUT_D, "Buildings", DEFAULT_PROPERTIES);
+    // verify
+    Map<String, Object> properties = result.getProperties();
+    assertNotNull(properties);
+    assertEquals("1", properties.get("Id"));
+    assertEquals("Building 1", properties.get("Name"));
+    assertNull(properties.get("Image"));
+    assertNull(properties.get("nb_Rooms"));
+
+    List<String> associationUris = result.getMetadata().getAssociationUris("nb_Rooms");
+    assertEquals(1, associationUris.size());
+    assertEquals("http://localhost:8080/ReferenceScenario.svc/Buildings('1')/nb_Rooms", associationUris.get(0));
+
+    checkMediaDataInitial(result.getMediaMetadata());
+  }
+
+  @Test
+  public void readMinimalEntry() throws Exception {
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+    EntityStream entityStream = new EntityStream();
+    entityStream.setContent(createContentAsStream("{\"Id\":\"99\"}"));
+    entityStream.setReadProperties(DEFAULT_PROPERTIES);
+    final ODataEntry result =
+        new JsonEntityDeserializer().readEntry(entitySet, entityStream);
+
+    final Map<String, Object> properties = result.getProperties();
+    assertNotNull(properties);
+    assertEquals(1, properties.size());
+    assertEquals("99", properties.get("Id"));
+
+    assertTrue(result.getMetadata().getAssociationUris("nt_Employees").isEmpty());
+    checkMediaDataInitial(result.getMediaMetadata());
+  }
+
+  @Test
+  public void readEntryWithNullProperty() throws Exception {
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+    final String content = "{\"Id\":\"99\",\"Seats\":null}";
+    
+    EntityStream entityStream = new EntityStream();
+    entityStream.setContent(createContentAsStream(content));
+    entityStream.setReadProperties(DeserializerProperties.init().build());
+    final ODataEntry result = new JsonEntityDeserializer().readEntry(entitySet, entityStream);
+
+    final Map<String, Object> properties = result.getProperties();
+    assertNotNull(properties);
+    assertEquals(2, properties.size());
+    assertEquals("99", properties.get("Id"));
+    assertTrue(properties.containsKey("Seats"));
+    assertNull(properties.get("Seats"));
+
+    assertTrue(result.getMetadata().getAssociationUris("nr_Employees").isEmpty());
+    checkMediaDataInitial(result.getMediaMetadata());
+    
+  }
+
+  @Test
+  public void readWithDoublePropertyOnTeam() throws Exception {
+    // The file contains the name property two times
+    try {
+      prepareAndExecuteEntry(INVALID_ENTRY_TEAM_DOUBLE_NAME_PROPERTY, "Teams", DEFAULT_PROPERTIES);
+      fail("Exception has to be thrown");
+    } catch (EntityProviderException e) {
+      assertEquals(EntityProviderException.DOUBLE_PROPERTY.getKey(), e.getMessageReference().getKey());
+    }
+  }
+
+  @Test
+  public void entryWithMetadataElementProperties() throws Exception {
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+    InputStream contentBody = createContentAsStream(
+        "{\"__metadata\":{\"properties\":{\"nt_Employees\":{\"associationuri\":"
+            + "\"http://some.host.com/service.root/Teams('1')/$links/nt_Employees\"}}},"
+            + "\"Id\":\"1\"}");
+    EntityStream entityStream = new EntityStream();
+    entityStream.setContent(contentBody);
+    entityStream.setReadProperties(DEFAULT_PROPERTIES);
+    ODataEntry result = new JsonEntityDeserializer().readEntry(entitySet, entityStream);
+    checkMediaDataInitial(result.getMediaMetadata());
+  }
+
+  private void checkMediaDataInitial(final MediaMetadata mediaMetadata) {
+    assertNull(mediaMetadata.getContentType());
+    assertNull(mediaMetadata.getEditLink());
+    assertNull(mediaMetadata.getEtag());
+    assertNull(mediaMetadata.getSourceLink());
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void emptyEntry() throws Exception {
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+    EntityStream entityStream = new EntityStream();
+    entityStream.setContent(createContentAsStream("{}"));
+    entityStream.setReadProperties(DEFAULT_PROPERTIES);
+    new JsonEntityDeserializer().readEntry(entitySet, entityStream);
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void wrongStart() throws Exception {
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+    InputStream contentBody = createContentAsStream(negativeJsonStart_1);
+    EntityStream entityStream = new EntityStream();
+    entityStream.setContent(contentBody);
+    entityStream.setReadProperties(DEFAULT_PROPERTIES);
+    new JsonEntityDeserializer().readEntry(entitySet, entityStream);
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void wrongStart2() throws Exception {
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+    InputStream contentBody = createContentAsStream(negativeJsonStart_2);
+    EntityStream entityStream = new EntityStream();
+    entityStream.setContent(contentBody);
+    entityStream.setReadProperties(DEFAULT_PROPERTIES);
+    new JsonEntityDeserializer().readEntry(entitySet, entityStream);
+  }
+  
+  /**
+   * Employee with inline entity Room with inline entity Buildings 
+   * Scenario of 1:1:1 navigation
+   * E.g: Employees('1')?$expand=ne_Room/nr_Building
+   * @throws Exception
+   */
+  @Test
+  public void employeesEntryWithEmployeeToRoomToBuilding() throws Exception {
+    InputStream stream = getFileAsStream("JsonEmployeeInlineRoomBuilding.json");
+    assertNotNull(stream);
+    EntityStream entityStream = new EntityStream();
+    entityStream.setContent(stream);
+    entityStream.setReadProperties(DeserializerProperties.init()
+        .build());
+    
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+    JsonEntityDeserializer xec = new JsonEntityDeserializer();
+    ODataEntry result =
+        xec.readEntry(entitySet, entityStream);
+    assertNotNull(result);
+    assertEquals(10, result.getProperties().size());
+    assertEquals(5, ((ODataEntry)result.getProperties().get("ne_Room")).getProperties().size());
+    assertEquals(3, ((ODataEntry)((ODataEntry)result.getProperties().get("ne_Room")).getProperties()
+        .get("nr_Building")).getProperties().size());
+  }
+  /**
+   * Employee with inline entity Room with inline entity Buildings 
+   * Scenario of 1:1:1 navigation
+   * E.g: Employees('1')?$expand=ne_Room/nr_Building
+   * @throws Exception
+   */
+  @Test
+  public void employeesEntryWithEmployeeToRoomToBuildingWithTypeMappings() throws Exception {
+    InputStream stream = getFileAsStream("JsonEmployeeInlineRoomBuilding.json");
+    assertNotNull(stream);
+    EntityStream entityStream = new EntityStream();
+    entityStream.setContent(stream);
+    Map<String, Object> typeMappings = new HashMap<String, Object>();
+    typeMappings.put("EntryDate", java.sql.Timestamp.class);
+    typeMappings.put("Name", String.class);
+    entityStream.setReadProperties(DeserializerProperties.init().addTypeMappings(typeMappings)
+        .build());
+    
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+    JsonEntityDeserializer xec = new JsonEntityDeserializer();
+    ODataEntry result =
+        xec.readEntry(entitySet, entityStream);
+    assertNotNull(result);
+    assertEquals(10, result.getProperties().size());
+    assertEquals(5, ((ODataEntry)result.getProperties().get("ne_Room")).getProperties().size());
+    assertEquals(3, ((ODataEntry)((ODataEntry)result.getProperties().get("ne_Room")).getProperties()
+        .get("nr_Building")).getProperties().size());
+  }
+  /**
+   * Room has inline entity to Employees and has inline entry To Team
+   * Scenario of 1:n:1 navigation 
+   * E.g: Rooms('1')?$expand=nr_Employees/ne_Team
+   * @throws Exception
+   */
+  @Test
+  public void RoomEntryWithInlineEmployeeInlineTeam() throws Exception {
+    InputStream stream = getFileAsStream("JsonRoom_InlineEmployeesToTeam.json");
+    assertNotNull(stream);
+    EntityStream entityStream = new EntityStream();
+    entityStream.setContent(stream);
+    entityStream.setReadProperties(DeserializerProperties.init()
+        .build());
+
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+    JsonEntityDeserializer xec = new JsonEntityDeserializer();
+    ODataEntry result =
+        xec.readEntry(entitySet, entityStream);
+    assertNotNull(result);
+    assertEquals(5, result.getProperties().size());
+    for (ODataEntry employeeEntry : ((ODataFeed)result.getProperties().get("nr_Employees")).getEntries()) {
+      assertEquals(10, employeeEntry.getProperties().size());
+      assertEquals(3, ((ODataEntry)employeeEntry.getProperties().get("ne_Team")).getProperties().size());
+    }
+  }
+  /**
+   * Room has empty inline entity to Employees and has inline entry To Team
+   * E.g: Rooms('10')?$expand=nr_Employees/ne_Team
+   * @throws Exception
+   */
+  @Test
+  public void RoomEntryWithEmptyInlineEmployeeInlineTeam() throws Exception {
+    InputStream stream = getFileAsStream("JsonRoom_EmptyInlineEmployeesToTeam.json");
+    assertNotNull(stream);
+    EntityStream entityStream = new EntityStream();
+    entityStream.setContent(stream);
+    entityStream.setReadProperties(DeserializerProperties.init()
+        .build());
+
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+    JsonEntityDeserializer xec = new JsonEntityDeserializer();
+    ODataEntry result =
+        xec.readEntry(entitySet, entityStream);
+    assertNotNull(result);
+    assertEquals(5, result.getProperties().size());
+    assertEquals(0, ((ODataFeed)result.getProperties().get("nr_Employees")).getEntries().size());
+  }
+  /**
+   * @param inlineEntries
+   * @param feed
+   * @param entry
+   */
+  private void getExpandedData(Map<String, Object> inlineEntries, ODataEntry entry) {
+    assertNotNull(entry);
+    Map<String, ExpandSelectTreeNode> expandNodes = entry.getExpandSelectTree().getLinks();
+    for (Entry<String, ExpandSelectTreeNode> expand : expandNodes.entrySet()) {
+      assertNotNull(expand.getKey());
+      if (inlineEntries.containsKey(expand.getKey() + entry.getMetadata().getId())) {
+        if (inlineEntries.get(expand.getKey() + entry.getMetadata().getId()) instanceof ODataFeed) {
+          ODataFeed innerFeed = (ODataFeed) inlineEntries.get(expand.getKey() + entry.getMetadata().getId());
+          assertNotNull(innerFeed);
+          getExpandedData(inlineEntries, innerFeed);
+          entry.getProperties().put(expand.getKey(), innerFeed);
+        } else if (inlineEntries.get(expand.getKey() + entry.getMetadata().getId()) instanceof ODataEntry) {
+          ODataEntry innerEntry = (ODataEntry) inlineEntries.get(expand.getKey() + entry.getMetadata().getId());
+          assertNotNull(innerEntry);
+          getExpandedData(inlineEntries, innerEntry);
+          entry.getProperties().put(expand.getKey(), innerEntry);
+        }
+      }
+    }
+  }
+  /**
+   * @param inlineEntries
+   * @param feed
+   * @param entry
+   */
+  private void getExpandedData(Map<String, Object> inlineEntries, ODataFeed feed) {
+    assertNotNull(feed.getEntries());
+    List<ODataEntry> entries = feed.getEntries();
+    for (ODataEntry entry : entries) {
+      Map<String, ExpandSelectTreeNode> expandNodes = entry.getExpandSelectTree().getLinks();
+      for (Entry<String, ExpandSelectTreeNode> expand : expandNodes.entrySet()) {
+        assertNotNull(expand.getKey());
+        if (inlineEntries.containsKey(expand.getKey() + entry.getMetadata().getId())) {
+          if (inlineEntries.get(expand.getKey() + entry.getMetadata().getId()) instanceof ODataFeed) {
+            ODataFeed innerFeed = (ODataFeed) inlineEntries.get(expand.getKey() + entry.getMetadata().getId());
+            assertNotNull(innerFeed);
+            getExpandedData(inlineEntries, innerFeed);
+            feed.getEntries().get(feed.getEntries().indexOf(entry)).getProperties().put(expand.getKey(), innerFeed);
+          } else if (inlineEntries.get(expand.getKey() + entry.getMetadata().getId()) instanceof ODataEntry) {
+            ODataEntry innerEntry = (ODataEntry) inlineEntries.get(expand.getKey() + entry.getMetadata().getId());
+            assertNotNull(innerEntry);
+            getExpandedData(inlineEntries, innerEntry);
+            feed.getEntries().get(feed.getEntries().indexOf(entry)).getProperties().put(expand.getKey(), innerEntry);
+          }
+        }
+      }
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/deserializer/JsonErrorDocumentDeserializerTest.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/deserializer/JsonErrorDocumentDeserializerTest.java b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/deserializer/JsonErrorDocumentDeserializerTest.java
new file mode 100644
index 0000000..1548bd7
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/deserializer/JsonErrorDocumentDeserializerTest.java
@@ -0,0 +1,234 @@
+/*******************************************************************************
+ * 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.client.core.ep.deserializer;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.InputStream;
+import java.util.Locale;
+
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.processor.ODataErrorContext;
+import org.apache.olingo.odata2.client.core.ep.deserializer.JsonErrorDocumentDeserializer;
+import org.apache.olingo.odata2.testutil.helper.StringHelper;
+import org.junit.Test;
+
+/**
+ *  
+ */
+public class JsonErrorDocumentDeserializerTest extends AbstractDeserializerTest {
+
+  private static final String JSON_ERROR_DOCUMENT_SIMPLE = "{\"error\":{\"code\":\"ErrorCode\"," +
+      "\"message\":{\"lang\":\"en-US\",\"value\":\"Message\"}}}";
+  private static final String JSON_ERROR_DOCUMENT_NULL_LOCALE = "{\"error\":{\"code\":\"ErrorCode\"," +
+      "\"message\":{\"lang\":null,\"value\":\"Message\"}}}";
+  private static final String JSON_ERROR_DOCUMENT_INNER_ERROR = "{\"error\":{\"code\":\"ErrorCode\"," +
+      "\"message\":{\"lang\":\"en-US\",\"value\":\"Message\"}, \"innererror\":\"Some InnerError\"}}";
+  private static final String JSON_ERROR_DOCUMENT_INNER_ERROR_COMPLEX = "{\"error\":{\"code\":\"ErrorCode\"," +
+      "\"message\":{\"lang\":\"en-US\",\"value\":\"Message\"}, " +
+      "\"innererror\":{\"moreInner\":\"More Inner Error\"}}}";
+  private static final String JSON_ERROR_DOCUMENT_INNER_ERROR_COMPLEX_OBJECT = "{\"error\":{\"code\":\"ErrorCode\"," +
+      "\"message\":{\"lang\":\"en-US\",\"value\":\"Message\"}, " +
+      "\"innererror\":{\"moreInner\":\"More Inner Error\",\"secondInner\":\"Second\"}}}";
+  private static final String JSON_ERROR_DOCUMENT_INNER_ERROR_COMPLEX_ARRAY = "{\"error\":{\"code\":\"ErrorCode\"," +
+      "\"message\":{\"lang\":\"en-US\",\"value\":\"Message\"}, " +
+      "\"innererror\":{\"innerArray\":[\"More Inner Error\",\"Second\"]}}}";
+  private static final String JSON_ERROR_DOCUMENT_INVALID_JSON = "\"error\":{\"code\":\"ErrorCode\"," +
+      "\"message\":{\"lang\":\"en-US\",\"value\":\"Message\"}}}";
+  /* error document with name 'locale' instead of 'lang' for message object */
+  private static final String JSON_ERROR_DOCUMENT_UNKNOWN_CONTENT = "{\"error\":{\"code\":\"ErrorCode\"," +
+      "\"message\":{\"locale\":\"en-US\",\"value\":\"Message\"}}}";
+  /* error document without value for message object */
+  private static final String JSON_ERROR_DOCUMENT_INVALID_CONTENT = "{\"error\":{\"code\":\"ErrorCode\"," +
+      "\"message\":{\"lang\":\"en-US\"}}}";
+  private static final String JSON_ERROR_DOCUMENT_MISSING_MESSAGE = "{\"error\":{\"code\":\"ErrorCode\"}}";
+  private static final String JSON_ERROR_DOCUMENT_MISSING_CODE = "{\"error\":{" +
+      "\"message\":{\"lang\":\"en-US\",\"value\":\"Message\"}}}";
+  private static final String JSON_ERROR_DOCUMENT_MISSING_ERROR = "{\"code\":\"ErrorCode\"," +
+      "\"message\":{\"lang\":\"en-US\",\"value\":\"Message\"}}";
+  private JsonErrorDocumentDeserializer jedc = new JsonErrorDocumentDeserializer();
+
+  @Test
+  public void simpleErrorDocument() throws Exception {
+    InputStream in = StringHelper.encapsulate(JSON_ERROR_DOCUMENT_SIMPLE);
+    ODataErrorContext error = jedc.readError(in);
+
+    assertEquals("Wrong content type", "application/json", error.getContentType());
+    assertEquals("Wrong message", "Message", error.getMessage());
+    assertEquals("Wrong error code", "ErrorCode", error.getErrorCode());
+    assertEquals("Wrong locale for lang", Locale.US, error.getLocale());
+  }
+
+  @Test
+  public void localeNull() throws Exception {
+    InputStream in = StringHelper.encapsulate(JSON_ERROR_DOCUMENT_NULL_LOCALE);
+    ODataErrorContext error = jedc.readError(in);
+
+    assertEquals("Wrong content type", "application/json", error.getContentType());
+    assertEquals("Wrong message", "Message", error.getMessage());
+    assertEquals("Wrong error code", "ErrorCode", error.getErrorCode());
+    assertNull("Expected NULL for locale", error.getLocale());
+  }
+
+  @Test
+  public void innerError() throws Exception {
+    InputStream in = StringHelper.encapsulate(JSON_ERROR_DOCUMENT_INNER_ERROR);
+    ODataErrorContext error = jedc.readError(in);
+
+    assertEquals("Wrong content type", "application/json", error.getContentType());
+    assertEquals("Wrong message", "Message", error.getMessage());
+    assertEquals("Wrong error code", "ErrorCode", error.getErrorCode());
+    assertEquals("Wrong inner error", "Some InnerError", error.getInnerError());
+  }
+
+  @Test
+  public void innerErrorComplex() throws Exception {
+    InputStream in = StringHelper.encapsulate(JSON_ERROR_DOCUMENT_INNER_ERROR_COMPLEX);
+    ODataErrorContext error = jedc.readError(in);
+
+    assertEquals("Wrong content type", "application/json", error.getContentType());
+    assertEquals("Wrong message", "Message", error.getMessage());
+    assertEquals("Wrong error code", "ErrorCode", error.getErrorCode());
+    assertEquals("Wrong inner error", "{\"moreInner\":\"More Inner Error\"}", error.getInnerError());
+  }
+
+  @Test
+  public void innerErrorComplexObject() throws Exception {
+    InputStream in = StringHelper.encapsulate(JSON_ERROR_DOCUMENT_INNER_ERROR_COMPLEX_OBJECT);
+    ODataErrorContext error = jedc.readError(in);
+
+    assertEquals("Wrong content type", "application/json", error.getContentType());
+    assertEquals("Wrong message", "Message", error.getMessage());
+    assertEquals("Wrong error code", "ErrorCode", error.getErrorCode());
+    assertEquals("Wrong inner error",
+        "{\"moreInner\":\"More Inner Error\",\"secondInner\":\"Second\"}", error.getInnerError());
+  }
+
+  @Test
+  public void innerErrorComplexArray() throws Exception {
+    InputStream in = StringHelper.encapsulate(JSON_ERROR_DOCUMENT_INNER_ERROR_COMPLEX_ARRAY);
+    ODataErrorContext error = jedc.readError(in);
+
+    assertEquals("Wrong content type", "application/json", error.getContentType());
+    assertEquals("Wrong message", "Message", error.getMessage());
+    assertEquals("Wrong error code", "ErrorCode", error.getErrorCode());
+    assertEquals("Wrong inner error",
+        "{\"innerArray\":[\"More Inner Error\"\"Second\"]}", error.getInnerError());
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void invalidJson() throws EntityProviderException {
+    InputStream in = StringHelper.encapsulate(JSON_ERROR_DOCUMENT_INVALID_JSON);
+    try {
+      jedc.readError(in);
+      fail("Expected exception was not thrown");
+    } catch (EntityProviderException e) {
+      assertEquals(EntityProviderException.EXCEPTION_OCCURRED, e.getMessageReference());
+      throw e;
+    }
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void invalidEmptyDocument() throws EntityProviderException {
+    InputStream in = StringHelper.encapsulate("");
+    try {
+      jedc.readError(in);
+      fail("Expected exception was not thrown");
+    } catch (EntityProviderException e) {
+      assertEquals(EntityProviderException.EXCEPTION_OCCURRED, e.getMessageReference());
+      throw e;
+    }
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void nullParameter() throws EntityProviderException {
+    try {
+      jedc.readError(null);
+      fail("Expected exception was not thrown");
+    } catch (EntityProviderException e) {
+      assertEquals(EntityProviderException.INVALID_STATE, e.getMessageReference());
+      throw e;
+    }
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void invalidErrorDocumentUnknown() throws EntityProviderException {
+    InputStream in = StringHelper.encapsulate(JSON_ERROR_DOCUMENT_UNKNOWN_CONTENT);
+    try {
+      jedc.readError(in);
+      fail("Expected exception was not thrown");
+    } catch (EntityProviderException e) {
+      assertEquals(EntityProviderException.INVALID_STATE, e.getMessageReference());
+      throw e;
+    }
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void invalidErrorDocument() throws EntityProviderException {
+    InputStream in = StringHelper.encapsulate(JSON_ERROR_DOCUMENT_INVALID_CONTENT);
+    try {
+      jedc.readError(in);
+      fail("Expected exception was not thrown");
+    } catch (EntityProviderException e) {
+      assertEquals(EntityProviderException.MISSING_PROPERTY, e.getMessageReference());
+      throw e;
+    }
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void invalidErrorDocumentMissingError() throws EntityProviderException {
+    InputStream in = StringHelper.encapsulate(JSON_ERROR_DOCUMENT_MISSING_ERROR);
+    try {
+      jedc.readError(in);
+      fail("Expected exception was not thrown");
+    } catch (EntityProviderException e) {
+      assertEquals(EntityProviderException.INVALID_STATE, e.getMessageReference());
+      throw e;
+    }
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void invalidErrorDocumentMissingCode() throws EntityProviderException {
+    InputStream in = StringHelper.encapsulate(JSON_ERROR_DOCUMENT_MISSING_CODE);
+    try {
+      jedc.readError(in);
+      fail("Expected exception was not thrown");
+    } catch (EntityProviderException e) {
+      assertEquals(EntityProviderException.MISSING_PROPERTY, e.getMessageReference());
+      assertTrue(e.getMessage().contains("code"));
+      throw e;
+    }
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void invalidErrorDocumentMissingMessage() throws EntityProviderException {
+    InputStream in = StringHelper.encapsulate(JSON_ERROR_DOCUMENT_MISSING_MESSAGE);
+    try {
+      jedc.readError(in);
+      fail("Expected exception was not thrown");
+    } catch (EntityProviderException e) {
+      assertEquals(EntityProviderException.MISSING_PROPERTY, e.getMessageReference());
+      assertTrue(e.getMessage().contains("message"));
+      throw e;
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/deserializer/JsonFeedDeserializerTest.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/deserializer/JsonFeedDeserializerTest.java b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/deserializer/JsonFeedDeserializerTest.java
new file mode 100644
index 0000000..cb77d4e
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/deserializer/JsonFeedDeserializerTest.java
@@ -0,0 +1,689 @@
+/*******************************************************************************
+ * 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.client.core.ep.deserializer;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import java.io.InputStream;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.ep.entry.DeletedEntryMetadata;
+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.ODataDeltaFeed;
+import org.apache.olingo.odata2.api.ep.feed.ODataFeed;
+import org.apache.olingo.odata2.client.api.ep.DeserializerProperties;
+import org.apache.olingo.odata2.client.api.ep.EntityStream;
+import org.apache.olingo.odata2.testutil.mock.MockFacade;
+import org.junit.Test;
+
+import junit.framework.Assert;
+
+/**
+ *  
+ */
+public class JsonFeedDeserializerTest extends AbstractDeserializerTest {
+
+  @Test
+  public void teamsFeed() throws Exception {
+    ODataFeed feed = prepareAndExecuteFeed("JsonTeams.json", "Teams", DEFAULT_PROPERTIES);
+
+    List<ODataEntry> entries = feed.getEntries();
+    assertNotNull(entries);
+    assertEquals(2, entries.size());
+
+    // Team1
+    ODataEntry entry = entries.get(0);
+    Map<String, Object> properties = entry.getProperties();
+    assertNotNull(properties);
+    assertEquals("1", properties.get("Id"));
+    assertEquals("Team 1", properties.get("Name"));
+    assertEquals(Boolean.FALSE, properties.get("isScrumTeam"));
+    assertNull(properties.get("nt_Employees"));
+
+    List<String> associationUris = entry.getMetadata().getAssociationUris("nt_Employees");
+    assertEquals(1, associationUris.size());
+    assertEquals("http://localhost:8080/ReferenceScenario.svc/Teams('1')/nt_Employees", associationUris.get(0));
+
+    checkMediaDataInitial(entry.getMediaMetadata());
+
+    // Team2
+    entry = entries.get(1);
+    properties = entry.getProperties();
+    assertNotNull(properties);
+    assertEquals("2", properties.get("Id"));
+    assertEquals("Team 2", properties.get("Name"));
+    assertEquals(Boolean.TRUE, properties.get("isScrumTeam"));
+    assertNull(properties.get("nt_Employees"));
+
+    associationUris = entry.getMetadata().getAssociationUris("nt_Employees");
+    assertEquals(1, associationUris.size());
+    assertEquals("http://localhost:8080/ReferenceScenario.svc/Teams('2')/nt_Employees", associationUris.get(0));
+
+    checkMediaDataInitial(entry.getMediaMetadata());
+
+    // Check FeedMetadata
+    FeedMetadata feedMetadata = feed.getFeedMetadata();
+    assertNotNull(feedMetadata);
+    assertNull(feedMetadata.getInlineCount());
+    assertNull(feedMetadata.getNextLink());
+  }
+
+  @Test
+  public void teamsFeedWithoutD() throws Exception {
+    ODataFeed feed = prepareAndExecuteFeed("JsonTeamsWithoutD.json", "Teams", DEFAULT_PROPERTIES);
+
+    List<ODataEntry> entries = feed.getEntries();
+    assertNotNull(entries);
+    assertEquals(2, entries.size());
+
+    // Team1
+    ODataEntry entry = entries.get(0);
+    Map<String, Object> properties = entry.getProperties();
+    assertNotNull(properties);
+    assertEquals("1", properties.get("Id"));
+    assertEquals("Team 1", properties.get("Name"));
+    assertEquals(Boolean.FALSE, properties.get("isScrumTeam"));
+    assertNull(properties.get("nt_Employees"));
+
+    List<String> associationUris = entry.getMetadata().getAssociationUris("nt_Employees");
+    assertEquals(1, associationUris.size());
+    assertEquals("http://localhost:8080/ReferenceScenario.svc/Teams('1')/nt_Employees", associationUris.get(0));
+
+    checkMediaDataInitial(entry.getMediaMetadata());
+
+    // Team2
+    entry = entries.get(1);
+    properties = entry.getProperties();
+    assertNotNull(properties);
+    assertEquals("2", properties.get("Id"));
+    assertEquals("Team 2", properties.get("Name"));
+    assertEquals(Boolean.TRUE, properties.get("isScrumTeam"));
+    assertNull(properties.get("nt_Employees"));
+
+    associationUris = entry.getMetadata().getAssociationUris("nt_Employees");
+    assertEquals(1, associationUris.size());
+    assertEquals("http://localhost:8080/ReferenceScenario.svc/Teams('2')/nt_Employees", associationUris.get(0));
+
+    checkMediaDataInitial(entry.getMediaMetadata());
+
+    // Check FeedMetadata
+    FeedMetadata feedMetadata = feed.getFeedMetadata();
+    assertNotNull(feedMetadata);
+    assertNull(feedMetadata.getInlineCount());
+    assertNull(feedMetadata.getNextLink());
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void invalidDoubleClosingBrackets() throws Exception {
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+    String content = "{\"d\":{\"results\":[]}}}";
+    InputStream contentBody = createContentAsStream(content);
+    EntityStream entityStream = new EntityStream();
+    entityStream.setContent(contentBody);
+    entityStream.setReadProperties(DEFAULT_PROPERTIES);
+
+    // execute
+    JsonEntityDeserializer xec = new JsonEntityDeserializer();
+    xec.readFeed(entitySet, entityStream);
+  }
+
+  @Test
+  public void emptyFeed() throws Exception {
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+    String content = "{\"d\":{\"results\":[]}}";
+    InputStream contentBody = createContentAsStream(content);
+    EntityStream entityStream = new EntityStream();
+    entityStream.setContent(contentBody);
+    entityStream.setReadProperties(DEFAULT_PROPERTIES);
+
+    // execute
+    JsonEntityDeserializer xec = new JsonEntityDeserializer();
+    ODataFeed feed = xec.readFeed(entitySet, entityStream);
+    assertNotNull(feed);
+
+    List<ODataEntry> entries = feed.getEntries();
+    assertNotNull(entries);
+    assertEquals(0, entries.size());
+
+    FeedMetadata feedMetadata = feed.getFeedMetadata();
+    assertNotNull(feedMetadata);
+    assertNull(feedMetadata.getInlineCount());
+    assertNull(feedMetadata.getNextLink());
+  }
+
+  @Test
+  public void emptyFeedWithoutDAndResults() throws Exception {
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+    InputStream contentBody = createContentAsStream("[]");
+    EntityStream entityStream = new EntityStream();
+    entityStream.setContent(contentBody);
+    entityStream.setReadProperties(DEFAULT_PROPERTIES);
+    final ODataFeed feed = new JsonEntityDeserializer().readFeed(entitySet, entityStream);
+    assertNotNull(feed);
+    final List<ODataEntry> entries = feed.getEntries();
+    assertNotNull(entries);
+    assertEquals(0, entries.size());
+    final FeedMetadata feedMetadata = feed.getFeedMetadata();
+    assertNotNull(feedMetadata);
+    assertNull(feedMetadata.getInlineCount());
+    assertNull(feedMetadata.getNextLink());
+  }
+
+  @Test
+  public void emptyFeedWithoutResults() throws Exception {
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+    InputStream contentBody = createContentAsStream("{\"d\":[]}");
+    EntityStream entityStream = new EntityStream();
+    entityStream.setContent(contentBody);
+    entityStream.setReadProperties(DEFAULT_PROPERTIES);
+    final ODataFeed feed = new JsonEntityDeserializer().readFeed(entitySet, entityStream);
+    assertNotNull(feed);
+    final List<ODataEntry> entries = feed.getEntries();
+    assertNotNull(entries);
+    assertEquals(0, entries.size());
+    final FeedMetadata feedMetadata = feed.getFeedMetadata();
+    assertNotNull(feedMetadata);
+    assertNull(feedMetadata.getInlineCount());
+    assertNull(feedMetadata.getNextLink());
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void resultsNotPresent() throws Exception {
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+    InputStream contentBody = createContentAsStream("{\"d\":{}}");
+    EntityStream entityStream = new EntityStream();
+    entityStream.setContent(contentBody);
+    entityStream.setReadProperties(DEFAULT_PROPERTIES);
+    new JsonEntityDeserializer().readFeed(entitySet, entityStream);
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void countButNoResults() throws Exception {
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+    InputStream contentBody = createContentAsStream("{\"d\":{\"__count\":\"1\"}}");
+    EntityStream entityStream = new EntityStream();
+    entityStream.setContent(contentBody);
+    entityStream.setReadProperties(DEFAULT_PROPERTIES);
+    new JsonEntityDeserializer().readFeed(entitySet, entityStream);
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void wrongCountType() throws Exception {
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+    InputStream contentBody = createContentAsStream("{\"d\":{\"__count\":1,\"results\":[]}}");
+    EntityStream entityStream = new EntityStream();
+    entityStream.setContent(contentBody);
+    entityStream.setReadProperties(DEFAULT_PROPERTIES);
+    new JsonEntityDeserializer().readFeed(entitySet, entityStream);
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void wrongCountContent() throws Exception {
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+    InputStream contentBody = createContentAsStream("{\"d\":{\"__count\":\"one\",\"results\":[]}}");
+    EntityStream entityStream = new EntityStream();
+    entityStream.setContent(contentBody);
+    entityStream.setReadProperties(DEFAULT_PROPERTIES);
+    new JsonEntityDeserializer().readFeed(entitySet, entityStream);
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void negativeCount() throws Exception {
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+    InputStream contentBody = createContentAsStream("{\"d\":{\"__count\":\"-1\",\"results\":[]}}");
+    EntityStream entityStream = new EntityStream();
+    entityStream.setContent(contentBody);
+    entityStream.setReadProperties(DEFAULT_PROPERTIES);
+    new JsonEntityDeserializer().readFeed(entitySet, entityStream);
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void wrongNextType() throws Exception {
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+    InputStream contentBody = createContentAsStream("{\"d\":{\"results\":[],\"__next\":false}}");
+    EntityStream entityStream = new EntityStream();
+    entityStream.setContent(contentBody);
+    entityStream.setReadProperties(DEFAULT_PROPERTIES);
+    new JsonEntityDeserializer().readFeed(entitySet, entityStream);
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void wrongTag() throws Exception {
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+    InputStream contentBody = createContentAsStream("{\"d\":{\"__results\":null}}");
+    EntityStream entityStream = new EntityStream();
+    entityStream.setContent(contentBody);
+    entityStream.setReadProperties(DEFAULT_PROPERTIES);
+    new JsonEntityDeserializer().readFeed(entitySet, entityStream);
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void doubleCount() throws Exception {
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+    InputStream contentBody = createContentAsStream("{\"d\":{\"__count\":\"1\",\"__count\":\"2\",\"results\":[]}}");
+    EntityStream entityStream = new EntityStream();
+    entityStream.setContent(contentBody);
+    entityStream.setReadProperties(DEFAULT_PROPERTIES);
+    new JsonEntityDeserializer().readFeed(entitySet, entityStream);
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void doubleNext() throws Exception {
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+    InputStream contentBody = createContentAsStream("{\"d\":{\"results\":[],\"__next\":\"a\",\"__next\":\"b\"}}");
+    EntityStream entityStream = new EntityStream();
+    entityStream.setContent(contentBody);
+    entityStream.setReadProperties(DEFAULT_PROPERTIES);
+    new JsonEntityDeserializer().readFeed(entitySet, entityStream);
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void doubleResults() throws Exception {
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+    InputStream contentBody = createContentAsStream("{\"results\":{\"results\":[]}}");
+    EntityStream entityStream = new EntityStream();
+    entityStream.setContent(contentBody);
+    entityStream.setReadProperties(DEFAULT_PROPERTIES);
+    new JsonEntityDeserializer().readFeed(entitySet, entityStream);
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void doubleD() throws Exception {
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+    InputStream contentBody = createContentAsStream("{\"d\":{\"d\":[]}}");
+    EntityStream entityStream = new EntityStream();
+    entityStream.setContent(contentBody);
+    entityStream.setReadProperties(DEFAULT_PROPERTIES);
+    new JsonEntityDeserializer().readFeed(entitySet, entityStream);
+  }
+
+  @Test
+  public void teamsFeedWithCount() throws Exception {
+    ODataFeed feed = prepareAndExecuteFeed("JsonTeamsWithCount.json", "Teams", DEFAULT_PROPERTIES);
+
+    List<ODataEntry> entries = feed.getEntries();
+    assertNotNull(entries);
+    assertEquals(2, entries.size());
+
+    // Check FeedMetadata
+    FeedMetadata feedMetadata = feed.getFeedMetadata();
+    assertNotNull(feedMetadata);
+    assertEquals(Integer.valueOf(3), feedMetadata.getInlineCount());
+    assertNull(feedMetadata.getNextLink());
+  }
+
+  @Test
+  public void teamsFeedWithCountWithoutD() throws Exception {
+    ODataFeed feed = prepareAndExecuteFeed("JsonTeamsWithCountWithoutD.json", "Teams", DEFAULT_PROPERTIES);
+
+    List<ODataEntry> entries = feed.getEntries();
+    assertNotNull(entries);
+    assertEquals(2, entries.size());
+
+    // Check FeedMetadata
+    FeedMetadata feedMetadata = feed.getFeedMetadata();
+    assertNotNull(feedMetadata);
+    assertEquals(Integer.valueOf(3), feedMetadata.getInlineCount());
+    assertNull(feedMetadata.getNextLink());
+  }
+
+  @Test
+  public void feedWithInlineCountAndNextAndDelta() throws Exception {
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+    String content =
+        "{\"d\":{\"__count\":\"3\",\"results\":[{" +
+            "\"__metadata\":{\"id\":\"http://localhost:8080/ReferenceScenario.svc/Teams('1')\"," +
+            "\"uri\":\"http://localhost:8080/ReferenceScenario.svc/Teams('1')\",\"type\":\"RefScenario.Team\"}," +
+            "\"Id\":\"1\",\"Name\":\"Team 1\",\"isScrumTeam\":false,\"nt_Employees\":{\"__deferred\":{" +
+            "\"uri\":\"http://localhost:8080/ReferenceScenario.svc/Teams('1')/nt_Employees\"}}}]," +
+            "\"__next\":\"Rooms?$skiptoken=98&$inlinecount=allpages\",\"__delta\":\"deltalink\"}}";
+    assertNotNull(content);
+    InputStream contentBody = createContentAsStream(content);
+    EntityStream entityStream = new EntityStream();
+    entityStream.setContent(contentBody);
+    entityStream.setReadProperties(DEFAULT_PROPERTIES);
+
+    // execute
+    JsonEntityDeserializer xec = new JsonEntityDeserializer();
+    ODataFeed feed = xec.readFeed(entitySet, entityStream);
+    assertNotNull(feed);
+
+    List<ODataEntry> entries = feed.getEntries();
+    assertNotNull(entries);
+    assertEquals(1, entries.size());
+
+    FeedMetadata feedMetadata = feed.getFeedMetadata();
+    assertNotNull(feedMetadata);
+    assertEquals(Integer.valueOf(3), feedMetadata.getInlineCount());
+    assertEquals("Rooms?$skiptoken=98&$inlinecount=allpages", feedMetadata.getNextLink());
+    assertEquals("deltalink", feedMetadata.getDeltaLink());
+  }
+
+  @Test
+  public void feedWithTeamAndNextAndDelta() throws Exception {
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+    String content =
+        "{\"d\":{\"results\":[{" +
+            "\"__metadata\":{\"id\":\"http://localhost:8080/ReferenceScenario.svc/Teams('1')\"," +
+            "\"uri\":\"http://localhost:8080/ReferenceScenario.svc/Teams('1')\",\"type\":\"RefScenario.Team\"}," +
+            "\"Id\":\"1\",\"Name\":\"Team 1\",\"isScrumTeam\":false,\"nt_Employees\":{\"__deferred\":{" +
+            "\"uri\":\"http://localhost:8080/ReferenceScenario.svc/Teams('1')/nt_Employees\"}}}]," +
+            "\"__next\":\"Rooms?$skiptoken=98\"," +
+            "\"__delta\":\"http://localhost:8080/ReferenceScenario.svc/Teams?!deltatoken=4711\"}}";
+    assertNotNull(content);
+    InputStream contentBody = createContentAsStream(content);
+    EntityStream entityStream = new EntityStream();
+    entityStream.setContent(contentBody);
+    entityStream.setReadProperties(DEFAULT_PROPERTIES);
+
+    // execute
+    JsonEntityDeserializer xec = new JsonEntityDeserializer();
+    ODataFeed feed = xec.readFeed(entitySet, entityStream);
+    assertNotNull(feed);
+
+    List<ODataEntry> entries = feed.getEntries();
+    assertNotNull(entries);
+    assertEquals(1, entries.size());
+
+    FeedMetadata feedMetadata = feed.getFeedMetadata();
+    assertNotNull(feedMetadata);
+    assertEquals("Rooms?$skiptoken=98", feedMetadata.getNextLink());
+    assertEquals("http://localhost:8080/ReferenceScenario.svc/Teams?!deltatoken=4711", feedMetadata.getDeltaLink());
+  }
+
+  @Test
+  public void feedWithTeamAndDeltaAndDeletedEntriesWithoutWhen() throws Exception {
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+    String content =
+        "{\"d\":{\"results\":[{" +
+            "\"__metadata\":{\"id\":\"http://localhost:8080/ReferenceScenario.svc/Teams('1')\"," +
+            "\"uri\":\"http://localhost:8080/ReferenceScenario.svc/Teams('1')\",\"type\":\"RefScenario.Team\"}," +
+            "\"Id\":\"1\",\"Name\":\"Team 1\",\"isScrumTeam\":false,\"nt_Employees\":{\"__deferred\":{" +
+            "\"uri\":\"http://localhost:8080/ReferenceScenario.svc/Teams('1')/nt_Employees\"}}}" +
+            ",{ \"@odata.context\":\"$metadata#Teams/$deletedEntity\",\"id\":\"/Teams('2')\"}" +
+            "]," +
+            "\"__delta\":\"http://localhost:8080/ReferenceScenario.svc/Teams?!deltatoken=4711\"}}";
+    assertNotNull(content);
+    InputStream contentBody = createContentAsStream(content);
+    EntityStream entityStream = new EntityStream();
+    entityStream.setContent(contentBody);
+    entityStream.setReadProperties(DEFAULT_PROPERTIES);
+
+    // execute
+    JsonEntityDeserializer xec = new JsonEntityDeserializer();
+    ODataDeltaFeed feed = xec.readDeltaFeed(entitySet, entityStream);
+    assertNotNull(feed);
+
+    List<ODataEntry> entries = feed.getEntries();
+    assertNotNull(entries);
+    assertEquals(1, entries.size());
+
+    FeedMetadata feedMetadata = feed.getFeedMetadata();
+    assertNotNull(feedMetadata);
+    assertEquals("http://localhost:8080/ReferenceScenario.svc/Teams?!deltatoken=4711", feedMetadata.getDeltaLink());
+
+    List<DeletedEntryMetadata> deletedEntries = feed.getDeletedEntries();
+    assertEquals(1, deletedEntries.size());
+    assertEquals("/Teams('2')", deletedEntries.get(0).getUri());
+    assertNull(deletedEntries.get(0).getWhen());
+  }
+
+  @Test
+  public void feedWithTeamAndDeltaAndDeletedEntries() throws Exception {
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+    String content =
+        "{\"d\":{\"results\":[{" +
+            "\"__metadata\":{\"id\":\"http://localhost:8080/ReferenceScenario.svc/Teams('1')\"," +
+            "\"uri\":\"http://localhost:8080/ReferenceScenario.svc/Teams('1')\",\"type\":\"RefScenario.Team\"}," +
+            "\"Id\":\"1\",\"Name\":\"Team 1\",\"isScrumTeam\":false,\"nt_Employees\":{\"__deferred\":{" +
+            "\"uri\":\"http://localhost:8080/ReferenceScenario.svc/Teams('1')/nt_Employees\"}}}" +
+            ",{ \"@odata.context\":\"$metadata#Teams/$deletedEntity\"," +
+            "\"id\":\"/Teams('2')\"," +
+            "\"when\":\"\\/Date(1297187419617)\\/\" }" +
+            "]," +
+            "\"__delta\":\"http://localhost:8080/ReferenceScenario.svc/Teams?!deltatoken=4711\"}}";
+    assertNotNull(content);
+    InputStream contentBody = createContentAsStream(content);
+    EntityStream entityStream = new EntityStream();
+    entityStream.setContent(contentBody);
+    entityStream.setReadProperties(DEFAULT_PROPERTIES);
+
+    // execute
+    JsonEntityDeserializer xec = new JsonEntityDeserializer();
+    ODataDeltaFeed feed = xec.readDeltaFeed(entitySet, entityStream);
+    assertNotNull(feed);
+
+    List<ODataEntry> entries = feed.getEntries();
+    assertNotNull(entries);
+    assertEquals(1, entries.size());
+
+    FeedMetadata feedMetadata = feed.getFeedMetadata();
+    assertNotNull(feedMetadata);
+    assertEquals("http://localhost:8080/ReferenceScenario.svc/Teams?!deltatoken=4711", feedMetadata.getDeltaLink());
+
+    List<DeletedEntryMetadata> deletedEntries = feed.getDeletedEntries();
+    assertEquals(1, deletedEntries.size());
+    assertEquals("/Teams('2')", deletedEntries.get(0).getUri());
+    assertEquals(new Date(1297187419617l), deletedEntries.get(0).getWhen());
+  }
+
+  @Test
+  public void feedWithOnlyDeletedEntries() throws Exception {
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+    String content =
+        "{\"d\":{\"results\":[" +
+            "{ \"@odata.context\":\"$metadata#Teams/$deletedEntity\"," +
+            "\"id\":\"/Teams('2')\"," +
+            "\"when\":\"\\/Date(1297187419617)\\/\" }" +
+            "]," +
+            "\"__delta\":\"http://localhost:8080/ReferenceScenario.svc/Teams?!deltatoken=4711\"}}";
+    assertNotNull(content);
+    InputStream contentBody = createContentAsStream(content);
+    EntityStream entityStream = new EntityStream();
+    entityStream.setContent(contentBody);
+    entityStream.setReadProperties(DEFAULT_PROPERTIES);
+
+    // execute
+    JsonEntityDeserializer xec = new JsonEntityDeserializer();
+    ODataDeltaFeed feed = xec.readDeltaFeed(entitySet, entityStream);
+    assertNotNull(feed);
+
+    List<ODataEntry> entries = feed.getEntries();
+    assertNotNull(entries);
+    assertEquals(0, entries.size());
+
+    FeedMetadata feedMetadata = feed.getFeedMetadata();
+    assertNotNull(feedMetadata);
+    assertEquals("http://localhost:8080/ReferenceScenario.svc/Teams?!deltatoken=4711", feedMetadata.getDeltaLink());
+
+    List<DeletedEntryMetadata> deletedEntries = feed.getDeletedEntries();
+    assertEquals(1, deletedEntries.size());
+    assertEquals("/Teams('2')", deletedEntries.get(0).getUri());
+    assertEquals(new Date(1297187419617l), deletedEntries.get(0).getWhen());
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void feedWithInvalidDeletedEntryWhenValue() throws Exception {
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+    String content =
+        "{\"d\":{\"results\":[" +
+            "{ \"@odata.context\":\"$metadata#Teams/$deletedEntity\"," +
+            "\"id\":\"/Teams('2')\"," +
+            "\"when\":\"1297187419617\" }" +
+            "]," +
+            "\"__delta\":\"http://localhost:8080/ReferenceScenario.svc/Teams?!deltatoken=4711\"}}";
+    assertNotNull(content);
+    InputStream contentBody = createContentAsStream(content);
+    EntityStream entityStream = new EntityStream();
+    entityStream.setContent(contentBody);
+    entityStream.setReadProperties(DEFAULT_PROPERTIES);
+
+    // execute
+    JsonEntityDeserializer xec = new JsonEntityDeserializer();
+    try {
+      xec.readDeltaFeed(entitySet, entityStream);
+    } catch (EntityProviderException e) {
+      assertEquals(EntityProviderException.INVALID_DELETED_ENTRY_METADATA, e.getMessageReference());
+      throw e;
+    }
+  }
+
+  @Test
+  public void feedWithRoomAndDeltaAndDeletedEntries() throws Exception {
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+    String content = readFile("JsonWithDeletedEntries.json");
+    assertNotNull(content);
+    InputStream contentBody = createContentAsStream(content);
+    EntityStream entityStream = new EntityStream();
+    entityStream.setContent(contentBody);
+    entityStream.setReadProperties(DEFAULT_PROPERTIES);
+
+    // execute
+    JsonEntityDeserializer xec = new JsonEntityDeserializer();
+    ODataDeltaFeed feed = xec.readDeltaFeed(entitySet, entityStream);
+    assertNotNull(feed);
+
+    List<ODataEntry> entries = feed.getEntries();
+    assertNotNull(entries);
+    assertEquals(1, entries.size());
+
+    FeedMetadata feedMetadata = feed.getFeedMetadata();
+    assertNotNull(feedMetadata);
+    assertEquals("http://localhost:8080/ReferenceScenario.svc/Rooms?!deltatoken=4711", feedMetadata.getDeltaLink());
+
+    assertEquals("W/\"2\"", entries.get(0).getMetadata().getEtag());
+
+    List<DeletedEntryMetadata> deletedEntries = feed.getDeletedEntries();
+    assertEquals(2, deletedEntries.size());
+    for (DeletedEntryMetadata deletedEntry : deletedEntries) {
+      String uri = deletedEntry.getUri();
+      if (uri.contains("Rooms('4')")) {
+        assertEquals("http://host:80/service/Rooms('4')", deletedEntry.getUri());
+        assertEquals(new Date(3509636760000l), deletedEntry.getWhen());
+      } else if (uri.contains("Rooms('3')")) {
+        assertEquals("http://host:80/service/Rooms('3')", deletedEntry.getUri());
+        assertEquals(new Date(1300561560000l), deletedEntry.getWhen());
+      } else {
+        Assert.fail("Found unknown DeletedEntry with value: " + deletedEntry);
+      }
+    }
+  }
+
+  private void checkMediaDataInitial(final MediaMetadata mediaMetadata) {
+    assertNull(mediaMetadata.getContentType());
+    assertNull(mediaMetadata.getEditLink());
+    assertNull(mediaMetadata.getEtag());
+    assertNull(mediaMetadata.getSourceLink());
+  }
+  /**
+   * Room has an Inline Feed Employees and Employee has an inline Entry Team
+   * E.g: Rooms?$expand=nr_Employees/ne_Team
+   * Empty Inline entity is also part of payload
+   * @throws Exception
+   */
+  @Test
+  public void roomsFeedWithRoomInlineEmployeesWithTeams() throws Exception {
+    InputStream stream = getFileAsStream("JsonRooms_InlineEmployeesTeams.json");
+    assertNotNull(stream);
+    
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+    JsonEntityDeserializer xec = new JsonEntityDeserializer();
+    EntityStream entityStream = new EntityStream();
+    entityStream.setContent(stream);
+    entityStream.setReadProperties(DeserializerProperties.init()
+        .build());
+    
+    ODataDeltaFeed feed = xec.readDeltaFeed(entitySet, entityStream);
+    assertNotNull(feed);
+    
+    assertEquals(3, feed.getEntries().size());
+
+    for (ODataEntry entry : feed.getEntries()) {
+      assertEquals(5, entry.getProperties().size());
+      for (ODataEntry innerEntry : ((ODataFeed)entry.getProperties().get("nr_Employees")).getEntries()) {
+        assertEquals(10, innerEntry.getProperties().size());
+        assertEquals(3, ((ODataEntry)innerEntry.getProperties().get("ne_Team")).getProperties().size());
+      }
+    }
+  }
+  
+  /**
+   * Rooms has an inline feed Employees and Rooms has Inline entry Buildings
+   * E.g: Rooms?$expand=nr_Employees,nr_Building
+   * Empty Inline entity is also part of payload
+   * @throws Exception
+   */
+  @Test
+  public void roomsFeedWithRoomInlineEmployeesInlineBuildings() throws Exception {
+    InputStream stream = getFileAsStream("JsonRooms_InlineEmployees_InlineBuilding.json");
+    assertNotNull(stream);
+    
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+    JsonEntityDeserializer xec = new JsonEntityDeserializer();
+    EntityStream entityStream = new EntityStream();
+    entityStream.setContent(stream);
+    entityStream.setReadProperties(DeserializerProperties.init()
+        .build());
+    ODataDeltaFeed feed = xec.readDeltaFeed(entitySet, entityStream);
+    assertNotNull(feed);
+    assertEquals(3, feed.getEntries().size());
+
+    for (ODataEntry entry : feed.getEntries()) {
+      assertEquals(6, entry.getProperties().size());
+      for (ODataEntry employeeEntry : ((ODataFeed)entry.getProperties().get("nr_Employees")).getEntries()) {
+        assertEquals(9, employeeEntry.getProperties().size());
+      }
+      assertEquals(3, ((ODataEntry)entry.getProperties().get("nr_Building")).getProperties().size());
+    }
+  }
+  
+  /**
+   * Rooms navigate to Employees and has inline entry Teams
+   * E.g: Rooms('1')/nr_Employees?$expand=ne_Team
+   * @throws Exception
+   */
+  @Test
+  public void roomsFeedWithRoomsToEmployeesInlineTeams() throws Exception {
+    InputStream stream = getFileAsStream("JsonRoomsToEmployeesWithInlineTeams.json");
+    assertNotNull(stream);
+    
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+    JsonEntityDeserializer xec = new JsonEntityDeserializer();
+    EntityStream entityStream = new EntityStream();
+    entityStream.setContent(stream);
+    entityStream.setReadProperties(DeserializerProperties.init()
+        .build());
+    ODataDeltaFeed feed = xec.readDeltaFeed(entitySet, entityStream);
+    assertNotNull(feed);
+    assertEquals(2, feed.getEntries().size());
+
+    for (ODataEntry entry : feed.getEntries()) {
+      assertEquals(10, entry.getProperties().size());
+      assertEquals(3, ((ODataEntry)entry.getProperties().get("ne_Team")).getProperties().size());
+    }
+  }
+}


[07/24] olingo-odata2 git commit: [OLINGO-1253]Client Module for Olingo v2

Posted by ar...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/serializer/JsonFeedEntitySerializerTest.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/serializer/JsonFeedEntitySerializerTest.java b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/serializer/JsonFeedEntitySerializerTest.java
new file mode 100644
index 0000000..23f3310
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/serializer/JsonFeedEntitySerializerTest.java
@@ -0,0 +1,919 @@
+/*******************************************************************************
+ * 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.client.core.ep.serializer;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmFacets;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.edm.EdmTyped;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.processor.ODataResponse;
+import org.apache.olingo.odata2.client.api.ep.Entity;
+import org.apache.olingo.odata2.client.api.ep.EntityCollection;
+import org.apache.olingo.odata2.client.api.ep.EntityCollectionSerializerProperties;
+import org.apache.olingo.odata2.client.api.ep.EntitySerializerProperties;
+import org.apache.olingo.odata2.client.core.ep.JsonSerializerDeserializer;
+import org.apache.olingo.odata2.testutil.fit.BaseTest;
+import org.apache.olingo.odata2.testutil.helper.StringHelper;
+import org.apache.olingo.odata2.testutil.mock.MockFacade;
+import org.junit.Test;
+
+/**
+ *  
+ */
+public class JsonFeedEntitySerializerTest extends BaseTest { 
+  protected static final String BASE_URI = "http://host:80/service/";
+  protected static final EntitySerializerProperties DEFAULT_PROPERTIES =
+      EntitySerializerProperties.serviceRoot(URI.create(BASE_URI)).build();
+  protected static final String ERROR_MSG = "Entity or expanded entity cannot have null value.";
+
+  @Test
+  public void unbalancedPropertyEntryWithInlineFeed() throws Exception {
+    Edm edm = MockFacade.getMockEdm();
+    EdmTyped imageUrlProperty = edm.getEntityType("RefScenario", "Employee").getProperty("ImageUrl");
+    EdmFacets facets = mock(EdmFacets.class);
+    when(facets.getMaxLength()).thenReturn(1);
+    when(((EdmProperty) imageUrlProperty).getFacets()).thenReturn(facets);
+
+    Entity roomData = new Entity();
+    roomData.addProperty("Id", "1");
+    roomData.addProperty("Name", "Neu Schwanstein");
+    roomData.addProperty("Seats", new Integer(20));
+
+    roomData.setWriteProperties(EntitySerializerProperties.serviceRoot(URI.create(BASE_URI))
+        .build());
+    EntityCollection innerData = new EntityCollection();
+    Entity data = new Entity();
+    data.addProperty("EmployeeId", "1");
+    data.addProperty("EmployeeName", "EmpName1");
+    data.addProperty("RoomId", "1");
+    data.setWriteProperties(DEFAULT_PROPERTIES);
+    innerData.addEntity(data);
+    
+    data = new Entity();
+    data.addProperty("EmployeeId", "1");
+    data.addProperty("RoomId", "1");
+    data.setWriteProperties(DEFAULT_PROPERTIES);
+    innerData.addEntity(data);
+    roomData.addNavigation("nr_Employees", innerData);
+
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Rooms");
+    final ODataResponse response =
+        new JsonSerializerDeserializer().writeEntry(entitySet, roomData);
+    assertNotNull(response);
+    assertNotNull(response.getEntity());
+
+    final String json = StringHelper.inputStreamToString((InputStream) response.getEntity());
+    assertNotNull(json);
+    assertEquals("{\"Id\":\"1\",\"Name\":\"Neu Schwanstein\",\"Seats\":20,\"nr_Employees\":"
+        + "[{\"EmployeeId\":\"1\",\"EmployeeName\":\"EmpName1\",\"RoomId\":\"1\"},"
+        + "{\"EmployeeId\":\"1\",\"RoomId\":\"1\"}]}", json);
+  }
+  
+  @Test
+  public void unbalancedPropertyEntryWithInlineFeedWithPropertiesInParent() throws Exception {
+    Edm edm = MockFacade.getMockEdm();
+    EdmTyped imageUrlProperty = edm.getEntityType("RefScenario", "Employee").getProperty("ImageUrl");
+    EdmFacets facets = mock(EdmFacets.class);
+    when(facets.getMaxLength()).thenReturn(1);
+    when(((EdmProperty) imageUrlProperty).getFacets()).thenReturn(facets);
+
+    Entity roomData = new Entity();
+    roomData.addProperty("Id", "1");
+    roomData.addProperty("Name", "Neu Schwanstein");
+    roomData.addProperty("Seats", new Integer(20));
+
+    roomData.setWriteProperties(EntitySerializerProperties.serviceRoot(URI.create(BASE_URI))
+        .build());
+    EntityCollection innerData = new EntityCollection();
+    Entity data = new Entity();
+    data.addProperty("EmployeeId", "1");
+    data.addProperty("EmployeeName", "EmpName1");
+    data.addProperty("RoomId", "1");
+    innerData.addEntity(data);
+    
+    data = new Entity();
+    data.addProperty("EmployeeId", "1");
+    data.addProperty("RoomId", "1");
+    innerData.addEntity(data);
+    roomData.addNavigation("nr_Employees", innerData);
+
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Rooms");
+    final ODataResponse response =
+        new JsonSerializerDeserializer().writeEntry(entitySet, roomData);
+    assertNotNull(response);
+    assertNotNull(response.getEntity());
+
+    final String json = StringHelper.inputStreamToString((InputStream) response.getEntity());
+    assertNotNull(json);
+    assertEquals("{\"Id\":\"1\",\"Name\":\"Neu Schwanstein\",\"Seats\":20,\"nr_Employees\":"
+        + "[{\"EmployeeId\":\"1\",\"EmployeeName\":\"EmpName1\",\"RoomId\":\"1\"},"
+        + "{\"EmployeeId\":\"1\",\"RoomId\":\"1\"}]}", json);
+  }
+  
+  @Test
+  public void unbalancedPropertyEntryWithEmptyInlineFeed() throws Exception {
+    Edm edm = MockFacade.getMockEdm();
+    EdmTyped imageUrlProperty = edm.getEntityType("RefScenario", "Employee").getProperty("ImageUrl");
+    EdmFacets facets = mock(EdmFacets.class);
+    when(facets.getMaxLength()).thenReturn(1);
+    when(((EdmProperty) imageUrlProperty).getFacets()).thenReturn(facets);
+
+    Entity roomData = new Entity();
+    roomData.addProperty("Id", "1");
+    roomData.addProperty("Name", "Neu Schwanstein");
+    roomData.addProperty("Seats", new Integer(20));
+
+    roomData.setWriteProperties(EntitySerializerProperties.serviceRoot(URI.create(BASE_URI))
+        .build());
+    EntityCollection innerData = new EntityCollection();
+    roomData.addNavigation("nr_Employees", innerData);
+
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Rooms");
+    ODataResponse response = new JsonSerializerDeserializer().writeEntry(entitySet, roomData);
+    assertNotNull(response);
+    assertNotNull(response.getEntity());
+    final String json = StringHelper.inputStreamToString((InputStream) response.getEntity());
+    assertEquals("{\"Id\":\"1\",\"Name\":\"Neu Schwanstein\",\"Seats\":20,\"nr_Employees\":"
+        + "[]}", json);
+  }
+  
+  @Test
+  public void unbalancedPropertyEntryWithPartialEmptyInlineFeed() throws Exception {
+    Edm edm = MockFacade.getMockEdm();
+    EdmTyped imageUrlProperty = edm.getEntityType("RefScenario", "Employee").getProperty("ImageUrl");
+    EdmFacets facets = mock(EdmFacets.class);
+    when(facets.getMaxLength()).thenReturn(1);
+    when(((EdmProperty) imageUrlProperty).getFacets()).thenReturn(facets);
+
+    Entity roomData = new Entity();
+    roomData.addProperty("Id", "1");
+    roomData.addProperty("Name", "Neu Schwanstein");
+    roomData.addProperty("Seats", new Integer(20));
+
+    roomData.setWriteProperties(EntitySerializerProperties.serviceRoot(URI.create(BASE_URI))
+        .build());
+    EntityCollection innerData = new EntityCollection();
+    Entity data = new Entity();
+    data.addProperty("EmployeeId", "1");
+    data.addProperty("EmployeeName", "EmpName1");
+    data.addProperty("RoomId", "1");
+    data.setWriteProperties(DEFAULT_PROPERTIES);
+    innerData.addEntity(data);
+    
+    data = new Entity();
+    innerData.addEntity(data);
+    roomData.addNavigation("nr_Employees", innerData);
+
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Rooms");
+    ODataResponse response = new JsonSerializerDeserializer().writeEntry(entitySet, roomData);
+    assertNotNull(response);
+    assertNotNull(response.getEntity());
+    final String json = StringHelper.inputStreamToString((InputStream) response.getEntity());
+    assertEquals("{\"Id\":\"1\",\"Name\":\"Neu Schwanstein\",\"Seats\":20,\"nr_Employees\":"
+        + "[{\"EmployeeId\":\"1\",\"EmployeeName\":\"EmpName1\",\"RoomId\":\"1\"},{}]}", json);
+  }
+  
+  @Test
+  public void entryWithExpandedFeedButEmptyEntityCollection() throws Exception {
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Buildings");
+    Entity buildingData = new Entity();
+    buildingData.addProperty("Id", "1");
+    buildingData.setWriteProperties(DEFAULT_PROPERTIES);
+    
+    EntityCollection roomCollection = new EntityCollection();
+    Entity roomData = new Entity();
+    roomCollection.addEntity(roomData);
+    buildingData.addNavigation("nb_Rooms", roomCollection);
+
+    ODataResponse response = new JsonSerializerDeserializer().writeEntry(entitySet, buildingData);
+    assertNotNull(response);
+    assertNotNull(response.getEntity());
+    final String json = StringHelper.inputStreamToString((InputStream) response.getEntity());
+    assertEquals("{\"Id\":\"1\",\"nb_Rooms\":[{}]}", json);
+  }
+
+  @Test
+  public void entryWithExpandedFeedButNullEntityCollection() throws Exception {
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Buildings");
+    Entity buildingData = new Entity();
+    buildingData.addProperty("Id", "1");
+    buildingData.setWriteProperties(DEFAULT_PROPERTIES);
+    
+    EntityCollection roomCollection = new EntityCollection();
+    roomCollection.addEntity(null);
+    buildingData.addNavigation("nb_Rooms", roomCollection);
+
+    try {
+      new JsonSerializerDeserializer().writeEntry(entitySet, buildingData);
+    } catch (EntityProviderException e) {
+      assertEquals(ERROR_MSG, e.getMessage());
+    }
+  }
+  
+  @Test
+  public void unbalancedPropertyEntryWithNullInlineFeed() throws Exception {
+    Edm edm = MockFacade.getMockEdm();
+    EdmTyped imageUrlProperty = edm.getEntityType("RefScenario", "Employee").getProperty("ImageUrl");
+    EdmFacets facets = mock(EdmFacets.class);
+    when(facets.getMaxLength()).thenReturn(1);
+    when(((EdmProperty) imageUrlProperty).getFacets()).thenReturn(facets);
+
+    Entity roomData = new Entity();
+    roomData.addProperty("Id", "1");
+    roomData.addProperty("Name", "Neu Schwanstein");
+    roomData.addProperty("Seats", new Integer(20));
+
+    roomData.setWriteProperties(EntitySerializerProperties.serviceRoot(URI.create(BASE_URI))
+        .build());
+    roomData.addNavigation("nr_Employees", null);
+
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Rooms");
+    try {
+      new JsonSerializerDeserializer().writeEntry(entitySet, roomData);
+    } catch (EntityProviderException e) {
+      assertEquals(ERROR_MSG, e.getMessage());
+    }
+  }
+  
+  @Test
+  public void entryWithExpandedEntryWithWritePropertiesOnCollection() throws Exception {
+    Edm edm = MockFacade.getMockEdm();
+    Entity roomData = new Entity();
+    roomData.addProperty("Id", "1");
+    roomData.addProperty("Name", "Neu Schwanstein");
+    roomData.addProperty("Seats", new Integer(20));
+    roomData.addProperty("Version", new Integer(3));
+    roomData.setWriteProperties(DEFAULT_PROPERTIES);
+    
+    EntityCollection employeeCollection = new EntityCollection();
+    Entity employeeData = new Entity();
+    employeeData.addProperty("EmployeeId", "1");
+    employeeData.addProperty("ImageUrl", "hhtp://url");
+    employeeCollection.addEntity(employeeData);
+    employeeCollection.setCollectionProperties
+    (EntityCollectionSerializerProperties.
+        serviceRoot(URI.create(BASE_URI)).build());
+    roomData.addNavigation("nr_Employees", employeeCollection);
+
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Rooms");
+    final ODataResponse response =
+        new JsonSerializerDeserializer().writeEntry(entitySet, roomData);
+    final String json = verifyResponse(response);
+    assertEquals("{\"Id\":\"1\",\"Name\":\"Neu Schwanstein\",\"Seats\":20,\"Version\":3,"
+        + "\"nr_Employees\":[{\"EmployeeId\":\"1\",\"ImageUrl\":\"hhtp://url\"}]}",
+        json);
+  }
+  
+  @Test
+  public void entryWithExpandedEntryWithGlobalWritePropertiesOnCollection() throws Exception {
+    Edm edm = MockFacade.getMockEdm();
+    Entity roomData = new Entity();
+    roomData.addProperty("Id", "1");
+    roomData.addProperty("Name", "Neu Schwanstein");
+    roomData.addProperty("Seats", new Integer(20));
+    roomData.addProperty("Version", new Integer(3));
+    roomData.setWriteProperties(DEFAULT_PROPERTIES);
+    
+    EntityCollection employeeCollection = new EntityCollection();
+    Entity employeeData = new Entity();
+    employeeData.addProperty("EmployeeId", "1");
+    employeeData.addProperty("ImageUrl", "hhtp://url");
+    employeeCollection.addEntity(employeeData);
+    employeeCollection.setGlobalEntityProperties(EntitySerializerProperties.
+        serviceRoot(URI.create(BASE_URI)).validatingFacets(true).build());
+    employeeCollection.setCollectionProperties
+    (EntityCollectionSerializerProperties.
+        serviceRoot(URI.create(BASE_URI)).build());
+    roomData.addNavigation("nr_Employees", employeeCollection);
+
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Rooms");
+    final ODataResponse response =
+        new JsonSerializerDeserializer().writeEntry(entitySet, roomData);
+    final String json = verifyResponse(response);
+    assertEquals("{\"Id\":\"1\",\"Name\":\"Neu Schwanstein\",\"Seats\":20,\"Version\":3,"
+        + "\"nr_Employees\":[{\"EmployeeId\":\"1\",\"ImageUrl\":\"hhtp://url\"}]}",
+        json);
+  }
+  
+  @Test
+  public void entryWithExpandedEntryWithoutKeyWithGlobalWritePropertiesOnCollection() throws Exception {
+    Edm edm = MockFacade.getMockEdm();
+    Entity roomData = new Entity();
+    roomData.addProperty("Id", "1");
+    roomData.addProperty("Name", "Neu Schwanstein");
+    roomData.addProperty("Seats", new Integer(20));
+    roomData.addProperty("Version", new Integer(3));
+    roomData.setWriteProperties(DEFAULT_PROPERTIES);
+    
+    EntityCollection employeeCollection = new EntityCollection();
+    Entity employeeData = new Entity();
+    employeeData.addProperty("EmployeeId", "1");
+    employeeData.addProperty("ImageUrl", "hhtp://url");
+    employeeCollection.addEntity(employeeData);
+    employeeCollection.setGlobalEntityProperties(EntitySerializerProperties.
+        serviceRoot(URI.create(BASE_URI)).validatingFacets(true).includeMetadata(true).build());
+    employeeCollection.setCollectionProperties
+    (EntityCollectionSerializerProperties.
+        serviceRoot(URI.create(BASE_URI)).build());
+    roomData.addNavigation("nr_Employees", employeeCollection);
+
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Rooms");
+    final ODataResponse response =
+        new JsonSerializerDeserializer().writeEntry(entitySet, roomData);
+    final String json = verifyResponse(response);
+    assertEquals("{\"Id\":\"1\",\"Name\":\"Neu Schwanstein\",\"Seats\":20,\"Version\":3,"
+        + "\"nr_Employees\":[{\"__metadata\":{\"id\":\"http://host:80/service/Employees('1')\",\"uri\":"
+        + "\"http://host:80/service/Employees('1')\",\"type\":\"RefScenario.Employee\",\"content_type\":"
+        + "\"application/octet-stream\",\"media_src\":\"http://host:80/service/Employees('1')/$value\","
+        + "\"edit_media\":\"http://host:80/service/Employees('1')/$value\"},\"EmployeeId\":\"1\","
+        + "\"ImageUrl\":\"hhtp://url\"}]}",
+        json);
+  }
+  
+  private String verifyResponse(final ODataResponse response) throws IOException {
+    assertNotNull(response);
+    assertNotNull(response.getEntity());
+    assertNull("EntitypProvider must not set content header", response.getContentHeader());
+
+    final String json = StringHelper.inputStreamToString((InputStream) response.getEntity());
+    assertNotNull(json);
+    return json;
+  }
+  
+  @Test
+  public void unbalancedPropertyEntryWithInlineFeedWithoutKey() throws Exception {
+    Edm edm = MockFacade.getMockEdm();
+    EdmTyped imageUrlProperty = edm.getEntityType("RefScenario", "Employee").getProperty("ImageUrl");
+    EdmFacets facets = mock(EdmFacets.class);
+    when(facets.getMaxLength()).thenReturn(1);
+    when(((EdmProperty) imageUrlProperty).getFacets()).thenReturn(facets);
+
+    Entity roomData = new Entity();
+    roomData.addProperty("Id", "1");
+    roomData.addProperty("Name", "Neu Schwanstein");
+    roomData.addProperty("Seats", new Integer(20));
+
+    roomData.setWriteProperties(EntitySerializerProperties.serviceRoot(URI.create(BASE_URI))
+        .build());
+    EntityCollection innerData = new EntityCollection();
+    Entity data = new Entity();
+    data.addProperty("EmployeeName", "EmpName1");
+    data.addProperty("RoomId", "1");
+    data.setWriteProperties(DEFAULT_PROPERTIES);
+    innerData.addEntity(data);
+    
+    data = new Entity();
+    data.addProperty("RoomId", "1");
+    data.setWriteProperties(DEFAULT_PROPERTIES);
+    innerData.addEntity(data);
+    roomData.addNavigation("nr_Employees", innerData);
+
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Rooms");
+    final ODataResponse response =
+        new JsonSerializerDeserializer().writeEntry(entitySet, roomData);
+    assertNotNull(response);
+    assertNotNull(response.getEntity());
+
+    final String json = StringHelper.inputStreamToString((InputStream) response.getEntity());
+    assertNotNull(json);
+    assertEquals("{\"Id\":\"1\",\"Name\":\"Neu Schwanstein\",\"Seats\":20,\"nr_Employees\":"
+        + "[{\"EmployeeName\":\"EmpName1\",\"RoomId\":\"1\"},"
+        + "{\"RoomId\":\"1\"}]}", json);
+  }
+  
+  @Test
+  public void unbalancedPropertyEntryWithoutKeyWithInlineFeed() throws Exception {
+    Edm edm = MockFacade.getMockEdm();
+    EdmTyped imageUrlProperty = edm.getEntityType("RefScenario", "Employee").getProperty("ImageUrl");
+    EdmFacets facets = mock(EdmFacets.class);
+    when(facets.getMaxLength()).thenReturn(1);
+    when(((EdmProperty) imageUrlProperty).getFacets()).thenReturn(facets);
+
+    Entity roomData = new Entity();
+    roomData.addProperty("Name", "Neu Schwanstein");
+    roomData.addProperty("Seats", new Integer(20));
+
+    roomData.setWriteProperties(EntitySerializerProperties.serviceRoot(URI.create(BASE_URI))
+        .build());
+    EntityCollection innerData = new EntityCollection();
+    Entity data = new Entity();
+    data.addProperty("EmployeeId", "1");
+    data.addProperty("EmployeeName", "EmpName1");
+    data.addProperty("RoomId", "1");
+    data.setWriteProperties(DEFAULT_PROPERTIES);
+    innerData.addEntity(data);
+    
+    data = new Entity();
+    data.addProperty("EmployeeId", "2");
+    data.addProperty("RoomId", "1");
+    data.setWriteProperties(DEFAULT_PROPERTIES);
+    innerData.addEntity(data);
+    roomData.addNavigation("nr_Employees", innerData);
+
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Rooms");
+    final ODataResponse response =
+        new JsonSerializerDeserializer().writeEntry(entitySet, roomData);
+    final String json = verifyResponse(response);
+    assertEquals("{\"Name\":\"Neu Schwanstein\",\"Seats\":20,\"nr_Employees\":"
+        + "[{\"EmployeeId\":\"1\",\"EmployeeName\":\"EmpName1\",\"RoomId\":\"1\"},"
+        + "{\"EmployeeId\":\"2\",\"RoomId\":\"1\"}]}",
+        json);
+  }
+  
+  @Test(expected=EntityProviderException.class)
+  public void unbalancedPropertyEntryWithoutKeyWithEmptyInlineFeedIncludingMetadata() throws Exception {
+    Edm edm = MockFacade.getMockEdm();
+    EdmTyped imageUrlProperty = edm.getEntityType("RefScenario", "Employee").getProperty("ImageUrl");
+    EdmFacets facets = mock(EdmFacets.class);
+    when(facets.getMaxLength()).thenReturn(1);
+    when(((EdmProperty) imageUrlProperty).getFacets()).thenReturn(facets);
+
+    Entity roomData = new Entity();
+    roomData.addProperty("Name", "Neu Schwanstein");
+    roomData.addProperty("Seats", new Integer(20));
+
+    roomData.setWriteProperties(EntitySerializerProperties.serviceRoot(URI.create(BASE_URI))
+        .includeMetadata(true).build());
+    EntityCollection innerData = new EntityCollection();
+    roomData.addNavigation("nr_Employees", innerData);
+
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Rooms");
+    new JsonSerializerDeserializer().writeEntry(entitySet, roomData);
+  }
+  
+  @Test
+  public void unbalancedPropertyEntryWithoutKeyWithNullInlineFeed() throws Exception {
+    Edm edm = MockFacade.getMockEdm();
+    EdmTyped imageUrlProperty = edm.getEntityType("RefScenario", "Employee").getProperty("ImageUrl");
+    EdmFacets facets = mock(EdmFacets.class);
+    when(facets.getMaxLength()).thenReturn(1);
+    when(((EdmProperty) imageUrlProperty).getFacets()).thenReturn(facets);
+
+    Entity roomData = new Entity();
+    roomData.addProperty("Name", "Neu Schwanstein");
+    roomData.addProperty("Seats", new Integer(20));
+
+    roomData.setWriteProperties(EntitySerializerProperties.serviceRoot(URI.create(BASE_URI))
+        .build());
+    roomData.addNavigation("nr_Employees", null);
+
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Rooms");
+    try {
+      new JsonSerializerDeserializer().writeEntry(entitySet, roomData);
+    } catch (EntityProviderException e) {
+      assertEquals(ERROR_MSG, e.getMessage());
+    }
+  }
+  
+  @Test
+  public void feed() throws Exception {
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+    EntityCollection teamsData = new EntityCollection();
+    Entity team1Data = new Entity();
+    team1Data.addProperty("Id", "1");
+    team1Data.addProperty("isScrumTeam", true);
+    Entity team2Data = new Entity();
+    team2Data.addProperty("Id", "2");
+    team2Data.addProperty("isScrumTeam", false);
+    teamsData.addEntity(team1Data);
+    teamsData.addEntity(team2Data);
+    teamsData.setCollectionProperties(EntityCollectionSerializerProperties.serviceRoot(URI.create(BASE_URI)).build());
+
+    final ODataResponse response = new JsonSerializerDeserializer().writeFeed(entitySet, teamsData);
+    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("{\"results\":[{\"Id\":\"1\",\"isScrumTeam\":true},{\"Id\":\"2\",\"isScrumTeam\":false}]}",
+        json);
+  }
+  
+  @Test
+  public void feedWithEmptyData() throws Exception {
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+    EntityCollection teamsData = new EntityCollection();
+    Entity team1Data = new Entity();
+    team1Data.addProperty("Id", "1");
+    team1Data.addProperty("isScrumTeam", true);
+    Entity team2Data = new Entity();
+    teamsData.addEntity(team1Data);
+    teamsData.addEntity(team2Data);
+    teamsData.setCollectionProperties(EntityCollectionSerializerProperties.serviceRoot(URI.create(BASE_URI)).build());
+
+    final ODataResponse response = new JsonSerializerDeserializer().writeFeed(entitySet, teamsData);
+    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("{\"results\":[{\"Id\":\"1\",\"isScrumTeam\":true},{}]}",
+        json);
+  }
+  
+  @Test
+  public void feedWithNullData() throws Exception {
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+    
+    try {
+      new JsonSerializerDeserializer().writeFeed(entitySet, null);
+    } catch (EntityProviderException e) {
+      assertEquals(ERROR_MSG, e.getMessage());
+    }
+  }
+  
+  @Test
+  public void feedWithMetadata() throws Exception {
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+    EntityCollection teamsData = new EntityCollection();
+    Entity team1Data = new Entity();
+    team1Data.addProperty("Id", "1");
+    team1Data.addProperty("isScrumTeam", true);
+    team1Data.setWriteProperties(EntitySerializerProperties.
+        serviceRoot(URI.create(BASE_URI)).includeMetadata(true).build());
+    Entity team2Data = new Entity();
+    team2Data.addProperty("Id", "2");
+    team2Data.addProperty("isScrumTeam", false);
+    teamsData.addEntity(team1Data);
+    teamsData.addEntity(team2Data);
+    teamsData.setCollectionProperties(EntityCollectionSerializerProperties.
+        serviceRoot(URI.create(BASE_URI)).build());
+
+    final ODataResponse response = new JsonSerializerDeserializer().writeFeed(entitySet, teamsData);
+    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("{\"results\":[{\"__metadata\":{\"id\":\"http://host:80/service/Teams('1')\","
+        + "\"uri\":\"http://host:80/service/Teams('1')\",\"type\":\"RefScenario.Team\"},"
+        + "\"Id\":\"1\",\"isScrumTeam\":true},{\"Id\":\"2\",\"isScrumTeam\":false}]}",
+        json);
+  }
+  
+  @Test
+  public void feedWithGlobalEntityProperties() throws Exception {
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+    EntityCollection teamsData = new EntityCollection();
+    Entity team1Data = new Entity();
+    team1Data.addProperty("Id", "1");
+    team1Data.addProperty("isScrumTeam", true);
+    Entity team2Data = new Entity();
+    team2Data.addProperty("Id", "2");
+    team2Data.addProperty("isScrumTeam", false);
+    teamsData.addEntity(team1Data);
+    teamsData.addEntity(team2Data);
+    teamsData.setCollectionProperties(EntityCollectionSerializerProperties.serviceRoot(URI.create(BASE_URI)).build());
+    teamsData.setGlobalEntityProperties(EntitySerializerProperties.serviceRoot(URI.create(BASE_URI)).
+        includeMetadata(true).build());
+    
+    final ODataResponse response = new JsonSerializerDeserializer().writeFeed(entitySet, teamsData);
+    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("{\"results\":[{\"__metadata\":{\"id\":\"http://host:80/service/Teams('1')\","
+        + "\"uri\":\"http://host:80/service/Teams('1')\",\"type\":\"RefScenario.Team\"},"
+        + "\"Id\":\"1\",\"isScrumTeam\":true},{\"__metadata\":"
+        + "{\"id\":\"http://host:80/service/Teams('2')\",\"uri\":"
+        + "\"http://host:80/service/Teams('2')\",\"type\":\"RefScenario.Team\"},"
+        + "\"Id\":\"2\",\"isScrumTeam\":false}]}",
+        json);
+  }
+  
+  @Test
+  public void feedWithPropertiesForEveryEntry() throws Exception {
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+    EntityCollection teamsData = new EntityCollection();
+    Entity team1Data = new Entity();
+    team1Data.addProperty("Id", "1");
+    team1Data.addProperty("isScrumTeam", true);
+    team1Data.setWriteProperties(EntitySerializerProperties.serviceRoot(URI.create(BASE_URI)).
+        includeMetadata(true).build());
+    Entity team2Data = new Entity();
+    team2Data.addProperty("Id", "2");
+    team2Data.addProperty("isScrumTeam", false);
+    team2Data.setWriteProperties(EntitySerializerProperties.serviceRoot(URI.create(BASE_URI)).
+        includeMetadata(true).build());
+    teamsData.addEntity(team1Data);
+    teamsData.addEntity(team2Data);
+    teamsData.setCollectionProperties(EntityCollectionSerializerProperties.serviceRoot(URI.create(BASE_URI)).build());
+    
+    final ODataResponse response = new JsonSerializerDeserializer().writeFeed(entitySet, teamsData);
+    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("{\"results\":[{\"__metadata\":{\"id\":\"http://host:80/service/Teams('1')\","
+        + "\"uri\":\"http://host:80/service/Teams('1')\",\"type\":\"RefScenario.Team\"},"
+        + "\"Id\":\"1\",\"isScrumTeam\":true},{\"__metadata\":"
+        + "{\"id\":\"http://host:80/service/Teams('2')\",\"uri\":"
+        + "\"http://host:80/service/Teams('2')\",\"type\":\"RefScenario.Team\"},"
+        + "\"Id\":\"2\",\"isScrumTeam\":false}]}",
+        json);
+  }
+  
+  @Test
+  public void unbalancedPropertyFeedWithInlineFeed() throws Exception {
+    Edm edm = MockFacade.getMockEdm();
+    EdmTyped imageUrlProperty = edm.getEntityType("RefScenario", "Employee").getProperty("ImageUrl");
+    EdmFacets facets = mock(EdmFacets.class);
+    when(facets.getMaxLength()).thenReturn(1);
+    when(((EdmProperty) imageUrlProperty).getFacets()).thenReturn(facets);
+
+    EntityCollection roomsData = new EntityCollection();
+    Entity room1Data = new Entity();
+    room1Data.addProperty("Id", "1");
+    room1Data.addProperty("Name", "Neu Schwanstein");
+    room1Data.addProperty("Seats", new Integer(20));
+    room1Data.setWriteProperties(EntitySerializerProperties.serviceRoot(URI.create(BASE_URI)).
+        validatingFacets(true).build());
+    
+    EntityCollection innerData = new EntityCollection();
+    Entity data = new Entity();
+    data.addProperty("EmployeeId", "1");
+    data.addProperty("EmployeeName", "EmpName1");
+    data.addProperty("RoomId", "1");
+    innerData.addEntity(data);
+    
+    data = new Entity();
+    data.addProperty("EmployeeId", "1");
+    data.addProperty("RoomId", "1");
+    innerData.addEntity(data);
+    
+    room1Data.addNavigation("nr_Employees", innerData);
+    roomsData.addEntity(room1Data);
+    
+    Entity room2Data = new Entity();
+    room2Data.addProperty("Id", "2");
+    room2Data.addProperty("Name", "John");
+    room2Data.addProperty("Seats", new Integer(10));
+    room2Data.setWriteProperties(EntitySerializerProperties.serviceRoot(URI.create(BASE_URI)).
+        validatingFacets(true).build());
+    
+    innerData = new EntityCollection();
+    data = new Entity();
+    data.addProperty("EmployeeId", "2");
+    data.addProperty("EmployeeName", "EmpName2");
+    data.addProperty("RoomId", "2");
+    innerData.addEntity(data);
+    
+    data = new Entity();
+    data.addProperty("EmployeeId", "2");
+    data.addProperty("RoomId", "2");
+    innerData.addEntity(data);
+    
+    room2Data.addNavigation("nr_Employees", innerData);
+    roomsData.addEntity(room2Data);
+    
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Rooms");
+    final ODataResponse response =
+        new JsonSerializerDeserializer().writeFeed(entitySet, roomsData);
+    assertNotNull(response);
+    assertNotNull(response.getEntity());
+
+    final String json = StringHelper.inputStreamToString((InputStream) response.getEntity());
+    assertNotNull(json);
+    assertEquals("{\"results\":[{\"Id\":\"1\",\"Name\":\"Neu Schwanstein\",\"Seats\":20,"
+        + "\"nr_Employees\":[{\"EmployeeId\":\"1\",\"EmployeeName\":\"EmpName1\",\"RoomId\":\"1\"},"
+        + "{\"EmployeeId\":\"1\",\"RoomId\":\"1\"}]},"
+        + "{\"Id\":\"2\",\"Name\":\"John\",\"Seats\":10,"
+        + "\"nr_Employees\":[{\"EmployeeId\":\"2\",\"EmployeeName\":\"EmpName2\",\"RoomId\":\"2\"},"
+        + "{\"EmployeeId\":\"2\",\"RoomId\":\"2\"}]}]}", json);
+  }
+  
+  @Test
+  public void unbalancedPropertyFeedWithInlineFeedAndNavigationLink() throws Exception {
+    Edm edm = MockFacade.getMockEdm();
+    EdmTyped imageUrlProperty = edm.getEntityType("RefScenario", "Employee").getProperty("ImageUrl");
+    EdmFacets facets = mock(EdmFacets.class);
+    when(facets.getMaxLength()).thenReturn(1);
+    when(((EdmProperty) imageUrlProperty).getFacets()).thenReturn(facets);
+
+    EntityCollection roomsData = new EntityCollection();
+    Entity room1Data = new Entity();
+    room1Data.addProperty("Id", "1");
+    room1Data.addProperty("Name", "Neu Schwanstein");
+    room1Data.addProperty("Seats", new Integer(20));
+    room1Data.setWriteProperties(EntitySerializerProperties.serviceRoot(URI.create(BASE_URI)).
+        validatingFacets(true).build());
+    
+    EntityCollection innerData = new EntityCollection();
+    Entity data = new Entity();
+    data.addProperty("EmployeeId", "1");
+    data.addProperty("EmployeeName", "EmpName1");
+    data.addProperty("RoomId", "1");
+    innerData.addEntity(data);
+    
+    data = new Entity();
+    data.addProperty("EmployeeId", "1");
+    data.addProperty("RoomId", "1");
+    innerData.addEntity(data);
+    
+    room1Data.addNavigation("nr_Employees", innerData);
+    Map<String, Object> link1 = new HashMap<String, Object>();
+    link1.put("Id", 1);
+    room1Data.addNavigation("nr_Building", link1);
+    roomsData.addEntity(room1Data);
+    
+    Entity room2Data = new Entity();
+    room2Data.addProperty("Id", "2");
+    room2Data.addProperty("Name", "John");
+    room2Data.addProperty("Seats", new Integer(10));
+    room2Data.setWriteProperties(EntitySerializerProperties.serviceRoot(URI.create(BASE_URI)).
+        validatingFacets(true).build());
+    
+    innerData = new EntityCollection();
+    data = new Entity();
+    data.addProperty("EmployeeId", "2");
+    data.addProperty("EmployeeName", "EmpName2");
+    data.addProperty("RoomId", "2");
+    innerData.addEntity(data);
+    
+    data = new Entity();
+    data.addProperty("EmployeeId", "2");
+    data.addProperty("RoomId", "2");
+    innerData.addEntity(data);
+    
+    room2Data.addNavigation("nr_Employees", innerData);
+    Map<String, Object> link2 = new HashMap<String, Object>();
+    link2.put("Id", 2);
+    room2Data.addNavigation("nr_Building", link2);
+    roomsData.addEntity(room2Data);
+    
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Rooms");
+    final ODataResponse response =
+        new JsonSerializerDeserializer().writeFeed(entitySet, roomsData);
+    assertNotNull(response);
+    assertNotNull(response.getEntity());
+
+    final String json = StringHelper.inputStreamToString((InputStream) response.getEntity());
+    assertNotNull(json);
+    assertEquals("{\"results\":[{\"Id\":\"1\",\"Name\":\"Neu Schwanstein\",\"Seats\":20,"
+        + "\"nr_Employees\":[{\"EmployeeId\":\"1\",\"EmployeeName\":\"EmpName1\",\"RoomId\":\"1\"},"
+        + "{\"EmployeeId\":\"1\",\"RoomId\":\"1\"}],\"nr_Building\":{\"__deferred\":"
+        + "{\"uri\":\"http://host:80/service/Buildings('1')\"}}},"
+        + "{\"Id\":\"2\",\"Name\":\"John\",\"Seats\":10,"
+        + "\"nr_Employees\":[{\"EmployeeId\":\"2\",\"EmployeeName\":\"EmpName2\",\"RoomId\":\"2\"},"
+        + "{\"EmployeeId\":\"2\",\"RoomId\":\"2\"}],\"nr_Building\":{\"__deferred\":"
+        + "{\"uri\":\"http://host:80/service/Buildings('2')\"}}}]}", json);
+  }
+  
+  @Test
+  public void unbalancedPropertyFeedWithInlineEntryAndNavigationLink() throws Exception {
+    Edm edm = MockFacade.getMockEdm();
+    EdmTyped imageUrlProperty = edm.getEntityType("RefScenario", "Employee").getProperty("ImageUrl");
+    EdmFacets facets = mock(EdmFacets.class);
+    when(facets.getMaxLength()).thenReturn(1);
+    when(((EdmProperty) imageUrlProperty).getFacets()).thenReturn(facets);
+
+    EntityCollection roomsData = new EntityCollection();
+    Entity room1Data = new Entity();
+    room1Data.addProperty("Id", "1");
+    room1Data.addProperty("Name", "Neu Schwanstein");
+    room1Data.addProperty("Seats", new Integer(20));
+    room1Data.setWriteProperties(EntitySerializerProperties.serviceRoot(URI.create(BASE_URI)).
+        validatingFacets(true).build());
+    
+    Map<String, Object> link1 = new HashMap<String, Object>();
+    link1.put("Id", 1);
+    room1Data.addNavigation("nr_Building", link1);
+    roomsData.addEntity(room1Data);
+    
+    Entity room2Data = new Entity();
+    room2Data.addProperty("Id", "2");
+    room2Data.addProperty("Name", "John");
+    room2Data.addProperty("Seats", new Integer(10));
+    room2Data.setWriteProperties(EntitySerializerProperties.serviceRoot(URI.create(BASE_URI)).
+        validatingFacets(true).build());
+    
+    Entity data = new Entity();
+    data.addProperty("Id", "2");
+    data.addProperty("Name", "Team2");
+    
+    room2Data.addNavigation("nr_Building", data);
+    roomsData.addEntity(room2Data);
+    
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Rooms");
+    final ODataResponse response =
+        new JsonSerializerDeserializer().writeFeed(entitySet, roomsData);
+    assertNotNull(response);
+    assertNotNull(response.getEntity());
+
+    final String json = StringHelper.inputStreamToString((InputStream) response.getEntity());
+    assertNotNull(json);
+    assertEquals("{\"results\":[{\"Id\":\"1\",\"Name\":\"Neu Schwanstein\",\"Seats\":20,"
+        + "\"nr_Building\":{\"__deferred\":{\"uri\":\"http://host:80/service/Buildings('1')\"}}},"
+        + "{\"Id\":\"2\",\"Name\":\"John\",\"Seats\":10,\"nr_Building\":"
+        + "{\"Id\":\"2\",\"Name\":\"Team2\"}}]}", json);
+  }
+  
+  @Test
+  public void unbalancedPropertyFeedWithInlineFeedAndNavigationLinkWithoutKeys() throws Exception {
+    Edm edm = MockFacade.getMockEdm();
+    EdmTyped imageUrlProperty = edm.getEntityType("RefScenario", "Employee").getProperty("ImageUrl");
+    EdmFacets facets = mock(EdmFacets.class);
+    when(facets.getMaxLength()).thenReturn(1);
+    when(((EdmProperty) imageUrlProperty).getFacets()).thenReturn(facets);
+
+    EntityCollection roomsData = new EntityCollection();
+    Entity room1Data = new Entity();
+    room1Data.addProperty("Name", "Neu Schwanstein");
+    room1Data.addProperty("Seats", new Integer(20));
+    room1Data.setWriteProperties(EntitySerializerProperties.serviceRoot(URI.create(BASE_URI)).
+        validatingFacets(false).isKeyAutoGenerated(true).build());
+    
+    EntityCollection innerData = new EntityCollection();
+    Entity data = new Entity();
+    data.addProperty("EmployeeName", "EmpName1");
+    data.addProperty("RoomId", "1");
+    innerData.addEntity(data);
+    
+    data = new Entity();
+    data.addProperty("RoomId", "1");
+    innerData.addEntity(data);
+    
+    room1Data.addNavigation("nr_Employees", innerData);
+    Map<String, Object> link1 = new HashMap<String, Object>();
+    link1.put("Id", 1);
+    room1Data.addNavigation("nr_Building", link1);
+    roomsData.addEntity(room1Data);
+    
+    Entity room2Data = new Entity();
+    room2Data.addProperty("Name", "John");
+    room2Data.addProperty("Seats", new Integer(10));
+    room2Data.setWriteProperties(EntitySerializerProperties.serviceRoot(URI.create(BASE_URI)).
+        validatingFacets(false).isKeyAutoGenerated(true).build());
+    
+    innerData = new EntityCollection();
+    data = new Entity();
+    data.addProperty("EmployeeName", "EmpName2");
+    data.addProperty("RoomId", "2");
+    innerData.addEntity(data);
+    
+    data = new Entity();
+    data.addProperty("RoomId", "2");
+    innerData.addEntity(data);
+    
+    room2Data.addNavigation("nr_Employees", innerData);
+    Map<String, Object> link2 = new HashMap<String, Object>();
+    link2.put("Id", 2);
+    room2Data.addNavigation("nr_Building", link2);
+    roomsData.addEntity(room2Data);
+    
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Rooms");
+    final ODataResponse response =
+        new JsonSerializerDeserializer().writeFeed(entitySet, roomsData);
+    assertNotNull(response);
+    assertNotNull(response.getEntity());
+
+    final String json = StringHelper.inputStreamToString((InputStream) response.getEntity());
+    assertNotNull(json);
+    assertEquals("{\"results\":[{\"Name\":\"Neu Schwanstein\",\"Seats\":20,"
+        + "\"nr_Employees\":[{\"EmployeeName\":\"EmpName1\",\"RoomId\":\"1\"},"
+        + "{\"RoomId\":\"1\"}],\"nr_Building\":{\"__deferred\":"
+        + "{\"uri\":\"http://host:80/service/Buildings('1')\"}}},"
+        + "{\"Name\":\"John\",\"Seats\":10,"
+        + "\"nr_Employees\":[{\"EmployeeName\":\"EmpName2\",\"RoomId\":\"2\"},"
+        + "{\"RoomId\":\"2\"}],\"nr_Building\":{\"__deferred\":"
+        + "{\"uri\":\"http://host:80/service/Buildings('2')\"}}}]}", json);
+  }
+
+}


[20/24] olingo-odata2 git commit: [OLINGO-1253]Client Module for Olingo v2

Posted by ar...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/XmlEntryDeserializer.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/XmlEntryDeserializer.java b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/XmlEntryDeserializer.java
new file mode 100644
index 0000000..06bae41
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/XmlEntryDeserializer.java
@@ -0,0 +1,596 @@
+/*******************************************************************************
+ * 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.client.core.ep.deserializer;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.namespace.NamespaceContext;
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmLiteralKind;
+import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
+import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
+import org.apache.olingo.odata2.api.edm.EdmSimpleType;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.ep.entry.ODataEntry;
+import org.apache.olingo.odata2.api.exception.ODataApplicationException;
+import org.apache.olingo.odata2.client.api.ep.DeserializerProperties;
+import org.apache.olingo.odata2.client.api.ep.callback.OnDeserializeInlineContent;
+import org.apache.olingo.odata2.core.commons.ContentType;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityInfoAggregator;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityPropertyInfo;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityTypeMapping;
+import org.apache.olingo.odata2.core.ep.entry.EntryMetadataImpl;
+import org.apache.olingo.odata2.core.ep.entry.MediaMetadataImpl;
+import org.apache.olingo.odata2.core.ep.entry.ODataEntryImpl;
+import org.apache.olingo.odata2.core.ep.feed.FeedMetadataImpl;
+import org.apache.olingo.odata2.core.ep.feed.ODataDeltaFeedImpl;
+import org.apache.olingo.odata2.core.ep.util.FormatXml;
+
+/**
+ * Atom/XML format reader/consumer for entries.
+ * 
+ * {@link XmlEntryDeserializer} instance can be reused for several
+ * {@link #readEntry(XMLStreamReader, EntityInfoAggregator, EntityProviderReadProperties)} calls
+ * but be aware that the instance and their <code>readEntry*</code> methods are <b>NOT THREAD SAFE</b>.
+ * 
+ */
+public class XmlEntryDeserializer {
+
+  private ODataEntryImpl readEntryResult;
+  private Map<String, Object> properties;
+  private MediaMetadataImpl mediaMetadata;
+  private EntryMetadataImpl entryMetadata;
+  private EntityTypeMapping typeMappings;
+  private String currentHandledStartTagName;
+
+  /**
+   * Deserializes payload entry
+   * @param reader
+   * @param eia
+   * @param readProperties
+   * @param isInline
+   * @return ODataEntry
+   * @throws EntityProviderException
+   */
+  public ODataEntry readEntry(final XMLStreamReader reader, final EntityInfoAggregator eia,
+      final DeserializerProperties readProperties, final boolean isInline) throws EntityProviderException {
+    try {
+      initialize(readProperties);
+
+      if (isInline) {
+        setETag(reader);
+      }
+
+      while (reader.hasNext() && !isEntryEndTag(reader)) {
+        reader.nextTag();
+        if (reader.isStartElement()) {
+          handleStartedTag(reader, eia, readProperties);
+        }
+      }
+
+      return readEntryResult;
+    } catch (XMLStreamException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass()
+          .getSimpleName()), e);
+    } catch (EdmException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass()
+          .getSimpleName()), e);
+    }
+  }
+
+  private boolean isEntryEndTag(final XMLStreamReader reader) {
+    return reader.isEndElement()
+        && Edm.NAMESPACE_ATOM_2005.equals(reader.getNamespaceURI())
+        && FormatXml.ATOM_ENTRY.equals(reader.getLocalName());
+  }
+
+  /**
+   * Initializes the {@link XmlEntryDeserializer} to be ready for reading an entry.
+   * @param readProperties
+   * @throws EntityProviderException
+   */
+  private void initialize(final DeserializerProperties readProperties) throws EntityProviderException {
+    properties = new HashMap<String, Object>();
+    mediaMetadata = new MediaMetadataImpl();
+    entryMetadata = new EntryMetadataImpl();
+    
+    readEntryResult = new ODataEntryImpl(properties, mediaMetadata, entryMetadata, null);
+    typeMappings = EntityTypeMapping.create(readProperties.getTypeMappings());
+  }
+
+  private void handleStartedTag(final XMLStreamReader reader, final EntityInfoAggregator eia,
+      final DeserializerProperties readProperties)
+      throws EntityProviderException, XMLStreamException, EdmException {
+
+    currentHandledStartTagName = reader.getLocalName();
+
+    if (FormatXml.ATOM_ID.equals(currentHandledStartTagName)) {
+      readId(reader);
+    } else if (FormatXml.ATOM_ENTRY.equals(currentHandledStartTagName)) {
+      readEntry(reader);
+    } else if (FormatXml.ATOM_LINK.equals(currentHandledStartTagName)) {
+      readLink(reader, eia, readProperties);
+    } else if (FormatXml.ATOM_CONTENT.equals(currentHandledStartTagName)) {
+      readContent(reader, eia, readProperties);
+    } else if (FormatXml.M_PROPERTIES.equals(currentHandledStartTagName)) {
+      readProperties(reader, eia, readProperties);
+    } else {
+      readCustomElement(reader, currentHandledStartTagName, eia, readProperties);
+    }
+  }
+
+  private void readCustomElement(final XMLStreamReader reader, final String tagName, //NOSONAR
+      final EntityInfoAggregator eia,
+      final DeserializerProperties readProperties)
+      throws EdmException, EntityProviderException, XMLStreamException { //NOSONAR
+    EntityPropertyInfo targetPathInfo = eia.getTargetPathInfo(tagName);
+    NamespaceContext nsctx = reader.getNamespaceContext();
+
+    boolean skipTag = true;
+    if (!Edm.NAMESPACE_ATOM_2005.equals(reader.getName().getNamespaceURI())) {
+
+      if (targetPathInfo != null) {
+        final String customPrefix = targetPathInfo.getCustomMapping().getFcNsPrefix();
+        final String customNamespaceURI = targetPathInfo.getCustomMapping().getFcNsUri();
+
+        if (customPrefix != null && customNamespaceURI != null) {
+          String xmlPrefix = nsctx.getPrefix(customNamespaceURI);
+          String xmlNamespaceUri = reader.getNamespaceURI(customPrefix);
+
+          if (customNamespaceURI.equals(xmlNamespaceUri) && customPrefix.equals(xmlPrefix)) { //NOSONAR
+            skipTag = false;
+            reader.require(XMLStreamConstants.START_ELEMENT, customNamespaceURI, tagName);
+            final String text = reader.getElementText();
+            reader.require(XMLStreamConstants.END_ELEMENT, customNamespaceURI, tagName);
+
+            final EntityPropertyInfo propertyInfo = getValidatedPropertyInfo(eia, tagName);
+            final Class<?> typeMapping = typeMappings.getMappingClass(propertyInfo.getName());
+            final EdmSimpleType type = (EdmSimpleType) propertyInfo.getType();
+            final Object value = type.valueOfString(text, EdmLiteralKind.DEFAULT,
+                readProperties == null || readProperties.isValidatingFacets() ? propertyInfo.getFacets() : null,
+                typeMapping == null ? type.getDefaultType() : typeMapping);
+            properties.put(tagName, value);
+          }
+        }
+      } else {
+        throw new EntityProviderException(EntityProviderException.INVALID_PROPERTY.addContent(tagName));
+      }
+    }
+
+    if (skipTag) {
+      skipStartedTag(reader);
+    }
+  }
+
+  /**
+   * Skip the tag to which the {@link XMLStreamReader} currently points.
+   * Therefore it is read until an end element tag with current local name is found.
+   * 
+   * @param reader
+   * @throws XMLStreamException
+   */
+  private void skipStartedTag(final XMLStreamReader reader) throws XMLStreamException {
+    final String name = reader.getLocalName();
+    int read = 1;
+    while (read > 0 && reader.hasNext()) {
+      reader.next();
+      if (reader.hasName() && name.equals(reader.getLocalName())) {
+        if (reader.isEndElement()) {
+          read--;
+        } else if (reader.isStartElement()) {
+          read++;
+        }
+      }
+    }
+  }
+
+  private void readEntry(final XMLStreamReader reader) throws XMLStreamException {
+    reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_ATOM_2005, FormatXml.ATOM_ENTRY);
+    setETag(reader);
+  }
+
+  private void setETag(final XMLStreamReader reader) {
+    final String etag = reader.getAttributeValue(Edm.NAMESPACE_M_2007_08, FormatXml.M_ETAG);
+    entryMetadata.setEtag(etag);
+  }
+
+  /**
+   * 
+   * @param reader
+   * @param eia
+   * @param readProperties
+   * @throws EntityProviderException
+   * @throws XMLStreamException
+   * @throws EdmException
+   */
+  private void readLink(final XMLStreamReader reader, final EntityInfoAggregator eia,
+      final DeserializerProperties readProperties) throws EntityProviderException, XMLStreamException,
+      EdmException {
+    reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_ATOM_2005, FormatXml.ATOM_LINK);
+
+    final String rel = reader.getAttributeValue(null, FormatXml.ATOM_REL);
+    final String uri = reader.getAttributeValue(null, FormatXml.ATOM_HREF);
+    final String type = reader.getAttributeValue(null, FormatXml.ATOM_TYPE);
+    final String etag = reader.getAttributeValue(Edm.NAMESPACE_M_2007_08, FormatXml.M_ETAG);
+
+    // read to next tag to check if <link> contains any further tags
+    reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_ATOM_2005, FormatXml.ATOM_LINK);
+    reader.nextTag();
+
+    if (rel == null || uri == null) {
+      throw new EntityProviderException(EntityProviderException.MISSING_ATTRIBUTE.addContent(
+          FormatXml.ATOM_HREF + "' and/or '" + FormatXml.ATOM_REL).addContent(FormatXml.ATOM_LINK));
+    } else if (rel.startsWith(Edm.NAMESPACE_REL_2007_08)) {
+      final String navigationPropertyName = rel.substring(Edm.NAMESPACE_REL_2007_08.length());
+      entryMetadata.putAssociationUri(navigationPropertyName, uri);
+    } else if (rel.equals(Edm.LINK_REL_EDIT_MEDIA)) {
+      mediaMetadata.setEditLink(uri);
+      mediaMetadata.setEtag(etag);
+    }
+
+    if (!reader.isEndElement() && rel != null && rel.startsWith(Edm.NAMESPACE_REL_2007_08)) {
+      readInlineContent(reader, eia, readProperties, type, rel);
+    }
+  }
+
+  /**
+   * Inline content was found and {@link XMLStreamReader} already points to <m:inline> tag.
+   * 
+   * @param reader
+   * @param eia
+   * @param readProperties
+   * @param atomLinkType the atom <code>type</code> attribute value of the <code>link</code> tag
+   * @param atomLinkRel the atom <code>rel</code> attribute value of the <code>link</code> tag
+   * @throws XMLStreamException
+   * @throws EntityProviderException
+   * @throws EdmException
+   */
+  private void readInlineContent(final XMLStreamReader reader, final EntityInfoAggregator eia,
+      final DeserializerProperties readProperties,
+      final String atomLinkType, final String atomLinkRel)
+      throws XMLStreamException, EntityProviderException, EdmException {
+
+    //
+    String navigationPropertyName = atomLinkRel.substring(Edm.NAMESPACE_REL_2007_08.length());
+
+    EdmNavigationProperty navigationProperty =
+        (EdmNavigationProperty) eia.getEntityType().getProperty(navigationPropertyName);
+    EdmEntitySet entitySet = eia.getEntitySet().getRelatedEntitySet(navigationProperty);
+    EntityInfoAggregator inlineEia = EntityInfoAggregator.create(entitySet);
+
+    final DeserializerProperties inlineProperties = createInlineProperties(readProperties, navigationProperty);
+
+    // validations
+    boolean isFeed = isInlineFeedValidated(reader, atomLinkType, navigationProperty);
+
+    List<ODataEntry> inlineEntries = new ArrayList<ODataEntry>();
+
+    while (!(reader.isEndElement() && Edm.NAMESPACE_M_2007_08.equals(reader.getNamespaceURI()) && FormatXml.M_INLINE
+        .equals(reader.getLocalName()))) {
+
+      if (reader.isStartElement() && Edm.NAMESPACE_ATOM_2005.equals(reader.getNamespaceURI())
+          && FormatXml.ATOM_ENTRY.equals(reader.getLocalName())) {
+        XmlEntryDeserializer xec = new XmlEntryDeserializer();
+        ODataEntry inlineEntry = xec.readEntry(reader, inlineEia, inlineProperties, true);
+        inlineEntries.add(inlineEntry);
+      }
+      // next tag
+      reader.next();
+    }
+
+    updateReadProperties(navigationPropertyName, isFeed, inlineEntries);
+
+    reader.require(XMLStreamConstants.END_ELEMENT, Edm.NAMESPACE_M_2007_08, FormatXml.M_INLINE);
+  }
+
+  /**
+   * Updates the read properties ({@link #properties}) for this {@link ReadEntryResult} ({@link #readEntryResult}).
+   * 
+   * @param readProperties
+   * @param navigationPropertyName
+   * @param navigationProperty
+   * @param isFeed
+   * @param inlineEntries
+   * @throws EntityProviderException
+   */
+  private void updateReadProperties(final String navigationPropertyName,
+      final boolean isFeed, 
+      final List<ODataEntry> inlineEntries) {
+    Object entry = extractODataEntity(isFeed, inlineEntries);
+    readEntryResult.setContainsInlineEntry(true);
+    properties.put(navigationPropertyName, entry);
+   
+  }
+
+  
+
+  /**
+   * Get a list of {@link ODataEntry}, an empty list, a single {@link ODataEntry} or <code>NULL</code> based on
+   * <code>isFeed</code> value and <code>inlineEntries</code> content.
+   * 
+   * @param isFeed
+   * @param inlineEntries
+   * @return
+   */
+  private Object extractODataEntity(final boolean isFeed, final List<ODataEntry> inlineEntries) {
+    if (isFeed) {
+      return new ODataDeltaFeedImpl(inlineEntries, new FeedMetadataImpl());
+    } else if (!inlineEntries.isEmpty()) {
+      return inlineEntries.get(0);
+    }
+    return null;
+  }
+
+
+  /**
+   * Create {@link EntityProviderReadProperties} which can be used for reading of inline properties/entrys of navigation
+   * links within
+   * this current read entry.
+   * 
+   * @param readProperties
+   * @param navigationProperty
+   * @return
+   * @throws EntityProviderException
+   */
+  private DeserializerProperties createInlineProperties
+  (final DeserializerProperties readProperties,
+      final EdmNavigationProperty navigationProperty) throws EntityProviderException {
+     final OnDeserializeInlineContent callback = readProperties.getCallback();
+
+     DeserializerProperties currentReadProperties = DeserializerProperties.initFrom(readProperties).build();
+    if (callback == null) {
+      return currentReadProperties;
+    } else {
+      try {
+        return callback.receiveReadProperties(currentReadProperties, navigationProperty);
+      } catch (ODataApplicationException e) {
+        throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass()
+            .getSimpleName()), e);
+      }
+    }
+  }
+
+  /**
+   * <p>
+   * Inline content was found and {@link XMLStreamReader} already points to <code><m:inline> tag</code>.
+   * <br/>
+   * <b>ATTENTION</b>: If {@link XMLStreamReader} does not point to the <code><m:inline> tag</code> an exception is
+   * thrown.
+   * </p>
+   * <p>
+   * Check whether it is an inline <code>Feed</code> or <code>Entry</code> and validate that...
+   * <ul>
+   * <li>...{@link FormatXml#M_INLINE} tag is correctly set.</li>
+   * <li>...based on {@link EdmMultiplicity} of {@link EdmNavigationProperty} all tags are correctly set.</li>
+   * <li>...{@link FormatXml#ATOM_TYPE} tag is correctly set and according to {@link FormatXml#ATOM_ENTRY} or
+   * {@link FormatXml#ATOM_FEED} to following tags are available.</li>
+   * </ul>
+   * 
+   * For the case that one of above validations fail an {@link EntityProviderException} is thrown.
+   * If validation was successful <code>true</code> is returned for <code>Feed</code> and <code>false</code> for
+   * <code>Entry</code>
+   * multiplicity.
+   * </p>
+   * 
+   * @param reader xml content reader which already points to <code><m:inline> tag</code>
+   * @param eia all necessary information about the entity
+   * @param type the atom type attribute value of the <code>link</code> tag
+   * @param navigationProperty the navigation property name of the entity
+   * @return <code>true</code> for <code>Feed</code> and <code>false</code> for <code>Entry</code>
+   * @throws EntityProviderException is thrown if at least one validation fails.
+   * @throws EdmException if edm access fails
+   */
+  private boolean isInlineFeedValidated(final XMLStreamReader reader,
+      final String type, final EdmNavigationProperty navigationProperty) throws EntityProviderException, EdmException {
+    boolean isFeed = false;
+    try {
+      reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_M_2007_08, FormatXml.M_INLINE);
+      //
+      ContentType cType = ContentType.parse(type);
+      if (cType == null) {
+        throw new EntityProviderException(EntityProviderException.INVALID_INLINE_CONTENT.addContent("xml data"));
+      }
+      EdmMultiplicity navigationMultiplicity = navigationProperty.getMultiplicity();
+
+      switch (navigationMultiplicity) {
+      case MANY:
+        validateFeedTags(reader, cType);
+        isFeed = true;
+        break;
+      case ONE:
+      case ZERO_TO_ONE:
+        validateEntryTags(reader, cType);
+        break;
+      }
+    } catch (XMLStreamException e) {
+      throw new EntityProviderException(EntityProviderException.INVALID_INLINE_CONTENT.addContent("xml data"), e);
+    }
+    return isFeed;
+  }
+
+  private void validateEntryTags(final XMLStreamReader reader, final ContentType cType) throws XMLStreamException,
+      EntityProviderException {
+    if (FormatXml.ATOM_ENTRY.equals(cType.getParameters().get(FormatXml.ATOM_TYPE))) {
+      int next = reader.nextTag();
+      if (XMLStreamConstants.START_ELEMENT == next) {
+        reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_ATOM_2005, FormatXml.ATOM_ENTRY);
+      } else {
+        reader.require(XMLStreamConstants.END_ELEMENT, Edm.NAMESPACE_M_2007_08, FormatXml.M_INLINE);
+      }
+    } else {
+      throw new EntityProviderException(EntityProviderException.INVALID_INLINE_CONTENT.addContent("entry"));
+    }
+  }
+
+  private void validateFeedTags(final XMLStreamReader reader, final ContentType cType) throws XMLStreamException,
+      EntityProviderException {
+    if (FormatXml.ATOM_FEED.equals(cType.getParameters().get(FormatXml.ATOM_TYPE))) {
+      int next = reader.nextTag();
+      if (XMLStreamConstants.START_ELEMENT == next) {
+        reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_ATOM_2005, FormatXml.ATOM_FEED);
+      } else {
+        reader.require(XMLStreamConstants.END_ELEMENT, Edm.NAMESPACE_M_2007_08, FormatXml.M_INLINE);
+      }
+    } else {
+      throw new EntityProviderException(EntityProviderException.INVALID_INLINE_CONTENT.addContent("feed"));
+    }
+  }
+
+  private void readContent(final XMLStreamReader reader, final EntityInfoAggregator eia,
+      final DeserializerProperties readProperties)
+      throws EntityProviderException, XMLStreamException, EdmException {
+    reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_ATOM_2005, FormatXml.ATOM_CONTENT);
+
+    final String contentType = reader.getAttributeValue(null, FormatXml.ATOM_TYPE);
+    final String sourceLink = reader.getAttributeValue(null, FormatXml.ATOM_SRC);
+
+    reader.nextTag();
+
+    if (reader.isStartElement() && reader.getLocalName().equals(FormatXml.M_PROPERTIES)) {
+      readProperties(reader, eia, readProperties);
+    } else if (reader.isEndElement()) {
+      reader.require(XMLStreamConstants.END_ELEMENT, Edm.NAMESPACE_ATOM_2005, FormatXml.ATOM_CONTENT);
+    } else {
+      throw new EntityProviderException(EntityProviderException.INVALID_STATE
+          .addContent("Expected closing 'content' or starting 'properties' but found '"
+              + reader.getLocalName() + "'."));
+    }
+
+    mediaMetadata.setContentType(contentType);
+    mediaMetadata.setSourceLink(sourceLink);
+  }
+
+  private void readId(final XMLStreamReader reader) throws EntityProviderException, XMLStreamException {
+    reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_ATOM_2005, FormatXml.ATOM_ID);
+    entryMetadata.setId(reader.getElementText());
+    reader.require(XMLStreamConstants.END_ELEMENT, Edm.NAMESPACE_ATOM_2005, FormatXml.ATOM_ID);
+  }
+
+  private void readProperties(final XMLStreamReader reader, final EntityInfoAggregator entitySet, //NOSONAR
+      final DeserializerProperties readProperties)
+      throws XMLStreamException, EdmException, EntityProviderException { 
+    // validate namespace
+    reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_M_2007_08, FormatXml.M_PROPERTIES);
+    if (entitySet.getEntityType().hasStream()) {
+      // external properties
+      checkCurrentHandledStartTag(FormatXml.M_PROPERTIES);
+    } else {
+      // inline properties
+      checkCurrentHandledStartTag(FormatXml.ATOM_CONTENT);
+    }
+
+    EntityPropertyInfo property;
+    XmlPropertyDeserializer xpc = new XmlPropertyDeserializer();
+
+    String closeTag = null;
+    boolean run = true;
+    reader.next();
+
+    while (run) {
+      if (reader.isStartElement() && closeTag == null) {
+        closeTag = reader.getLocalName();
+        if (isEdmNamespaceProperty(reader)) {
+          if (properties.containsKey(closeTag)) {
+            throw new EntityProviderException(EntityProviderException.DOUBLE_PROPERTY.addContent(closeTag));
+          }
+          property = getValidatedPropertyInfo(entitySet, closeTag);
+          final Object value = xpc.readStartedElement(reader, closeTag, property, typeMappings, readProperties);
+          properties.put(closeTag, value);
+          closeTag = null;
+        }
+      } else if (reader.isEndElement()) {
+        if (reader.getLocalName().equals(closeTag)) {
+          closeTag = null;
+        } else if (Edm.NAMESPACE_M_2007_08.equals(reader.getNamespaceURI())
+            && FormatXml.M_PROPERTIES.equals(reader.getLocalName())) {
+          run = false;
+        }
+      }
+      reader.next();
+    }
+  }
+
+  /**
+   * Check if the {@link #currentHandledStartTagName} is the same as the <code>expectedTagName</code>.
+   * If tag name is not as expected or if {@link #currentHandledStartTagName} is not set an
+   * {@link EntityProviderException} is thrown.
+   * 
+   * @param expectedTagName expected name for {@link #currentHandledStartTagName}
+   * @throws EntityProviderException if tag name is not as expected or if {@link #currentHandledStartTagName} is
+   * <code>NULL</code>.
+   */
+  private void checkCurrentHandledStartTag(final String expectedTagName) throws EntityProviderException {
+    if (currentHandledStartTagName == null) {
+      throw new EntityProviderException(EntityProviderException.INVALID_STATE
+          .addContent("No current handled start tag name set."));
+    } else if (!currentHandledStartTagName.equals(expectedTagName)) {
+      throw new EntityProviderException(EntityProviderException.INVALID_PARENT_TAG.addContent(expectedTagName)
+          .addContent(currentHandledStartTagName));
+    }
+  }
+
+  /**
+   * Checks if property of currently read tag in {@link XMLStreamReader} is defined in
+   * <code>edm properties namespace</code> {@value Edm#NAMESPACE_D_2007_08}.
+   * 
+   * If no namespace uri definition is found for namespace prefix of property (<code>tag</code>) an exception is thrown.
+   * 
+   * @param reader {@link XMLStreamReader} with position at to checked tag
+   * @return <code>true</code> if property is in <code>edm properties namespace</code>, otherwise <code>false</code>.
+   * @throws EntityProviderException If no namespace uri definition is found for namespace prefix of property
+   * (<code>tag</code>).
+   */
+  private boolean isEdmNamespaceProperty(final XMLStreamReader reader) throws EntityProviderException {
+    final String nsUri = reader.getNamespaceURI();
+    if (nsUri == null) {
+      throw new EntityProviderException(EntityProviderException.INVALID_NAMESPACE.addContent(reader.getLocalName()));
+    } else {
+      return Edm.NAMESPACE_D_2007_08.equals(nsUri);
+    }
+  }
+
+  /**
+   * Get validated {@link EntityPropertyInfo} for property with given <code>name</code>.
+   * If validation fails an {@link EntityProviderException} is thrown.
+   * 
+   * Currently this is the case if no {@link EntityPropertyInfo} if found for given <code>name</code>.
+   * 
+   * @param entitySet
+   * @param name
+   * @return valid {@link EntityPropertyInfo} (which is never <code>NULL</code>).
+   * @throws EntityProviderException
+   */
+  private EntityPropertyInfo getValidatedPropertyInfo(final EntityInfoAggregator entitySet, final String name)
+      throws EntityProviderException {
+    EntityPropertyInfo info = entitySet.getPropertyInfo(name);
+    if (info == null) {
+      throw new EntityProviderException(EntityProviderException.INVALID_PROPERTY.addContent(name));
+    }
+    return info;
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/XmlErrorDocumentDeserializer.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/XmlErrorDocumentDeserializer.java b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/XmlErrorDocumentDeserializer.java
new file mode 100644
index 0000000..dd22aa5
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/XmlErrorDocumentDeserializer.java
@@ -0,0 +1,184 @@
+/*******************************************************************************
+ * 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.client.core.ep.deserializer;
+
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.processor.ODataErrorContext;
+import org.apache.olingo.odata2.core.commons.ContentType;
+import org.apache.olingo.odata2.core.commons.XmlHelper;
+import org.apache.olingo.odata2.core.ep.util.FormatXml;
+
+/**
+ * Consuming (read / deserialization) for OData error document in XML format.
+ */
+public class XmlErrorDocumentDeserializer {
+  /**
+   * Map containing language code (language - country) to Locale mapping
+   * based on Locale.getAvailableLocales()
+   * */
+  private static final Map<String, Locale> AVAILABLE_LOCALES = new HashMap<String, Locale>();
+  static {
+    Locale[] locales = Locale.getAvailableLocales();
+    for (Locale l : locales) {
+      AVAILABLE_LOCALES.put(l.getLanguage() + "-" + l.getCountry(), l);
+    }
+  }
+
+  /**
+   * Deserialize / read OData error document in ODataErrorContext.
+   * 
+   * @param errorDocument OData error document in XML format
+   * @return created ODataErrorContext based on input stream content.
+   * @throws EntityProviderException if an exception during read / deserialization occurs.
+   */
+  public ODataErrorContext readError(final InputStream errorDocument) throws EntityProviderException {
+    XMLStreamReader reader = null;
+    EntityProviderException cachedException = null;
+
+    try {
+      reader = XmlHelper.createStreamReader(errorDocument);
+      return parserError(reader);
+    } catch (XMLStreamException e) {
+      cachedException = new EntityProviderException(EntityProviderException.INVALID_STATE.addContent(
+          e.getMessage()), e);
+      throw cachedException;
+    } catch (EntityProviderException e) {
+      cachedException = e;
+      throw cachedException;
+    } finally {//NOPMD  - suppressed
+      if (reader != null) {
+        try {
+          reader.close();
+        } catch (XMLStreamException e) {
+          if (cachedException != null) {
+            throw cachedException; //NOSONAR
+          } else {
+            throw new EntityProviderException( //NOSONAR
+                EntityProviderException.EXCEPTION_OCCURRED.addContent(
+                    e.getClass().getSimpleName()), e); 
+          }
+        }
+      }
+    }
+  }
+
+  private ODataErrorContext parserError(final XMLStreamReader reader)
+      throws XMLStreamException, EntityProviderException {
+    // read xml tag
+    reader.require(XMLStreamConstants.START_DOCUMENT, null, null);
+    reader.nextTag();
+
+    // read error tag
+    reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_M_2007_08, FormatXml.M_ERROR);
+
+    // read error data
+    boolean codeFound = false;
+    boolean messageFound = false;
+    ODataErrorContext errorContext = new ODataErrorContext();
+    while (notFinished(reader)) {
+      reader.nextTag();
+      if (reader.isStartElement()) {
+        String name = reader.getLocalName();
+        if (FormatXml.M_CODE.equals(name)) {
+          codeFound = true;
+          handleCode(reader, errorContext);
+        } else if (FormatXml.M_MESSAGE.equals(name)) {
+          messageFound = true;
+          handleMessage(reader, errorContext);
+        } else if (FormatXml.M_INNER_ERROR.equals(name)) {
+          handleInnerError(reader, errorContext);
+        } else {
+          throw new EntityProviderException(
+              EntityProviderException.INVALID_CONTENT.addContent(name, FormatXml.M_ERROR));
+        }
+      }
+    }
+    validate(codeFound, messageFound);
+
+    errorContext.setContentType(ContentType.APPLICATION_XML.toContentTypeString());
+    return errorContext;
+  }
+
+  private void validate(final boolean codeFound, final boolean messageFound) throws EntityProviderException {
+    if (!codeFound) {
+      throw new EntityProviderException(
+          EntityProviderException.MISSING_PROPERTY.addContent("Mandatory 'code' property not found.'"));
+    } else if (!messageFound) {
+      throw new EntityProviderException(
+          EntityProviderException.MISSING_PROPERTY.addContent("Mandatory 'message' property not found.'"));
+    }
+  }
+
+  private boolean notFinished(final XMLStreamReader reader) throws XMLStreamException {
+    return notFinished(reader, FormatXml.M_ERROR);
+  }
+
+  private boolean notFinished(final XMLStreamReader reader, final String tagName) throws XMLStreamException {
+    boolean finished = reader.isEndElement() && tagName.equals(reader.getLocalName());
+    return !finished && reader.hasNext();
+  }
+
+  private void handleInnerError(final XMLStreamReader reader, final ODataErrorContext errorContext)
+      throws XMLStreamException {
+
+    StringBuilder sb = new StringBuilder();
+    while (notFinished(reader, FormatXml.M_INNER_ERROR)) {
+      if (reader.hasName() && !FormatXml.M_INNER_ERROR.equals(reader.getLocalName())) {
+        sb.append("<");
+        if (reader.isEndElement()) {
+          sb.append("/");
+        }
+        sb.append(reader.getLocalName()).append(">");
+      } else if (reader.isCharacters()) {
+        sb.append(reader.getText());
+      }
+      reader.next();
+    }
+
+    errorContext.setInnerError(sb.toString());
+  }
+
+  private void handleMessage(final XMLStreamReader reader, final ODataErrorContext errorContext)
+      throws XMLStreamException {
+    String lang = reader.getAttributeValue(Edm.NAMESPACE_XML_1998, FormatXml.XML_LANG);
+    errorContext.setLocale(getLocale(lang));
+    String message = reader.getElementText();
+    errorContext.setMessage(message);
+  }
+
+  private void handleCode(final XMLStreamReader reader, final ODataErrorContext errorContext)
+      throws XMLStreamException {
+    String code = reader.getElementText();
+    errorContext.setErrorCode(code);
+  }
+
+  private Locale getLocale(final String langValue) {
+    return AVAILABLE_LOCALES.get(langValue);
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/XmlFeedDeserializer.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/XmlFeedDeserializer.java b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/XmlFeedDeserializer.java
new file mode 100644
index 0000000..f47d303
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/XmlFeedDeserializer.java
@@ -0,0 +1,226 @@
+/*******************************************************************************
+ * 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.client.core.ep.deserializer;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmLiteralKind;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeException;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.ep.entry.DeletedEntryMetadata;
+import org.apache.olingo.odata2.api.ep.entry.ODataEntry;
+import org.apache.olingo.odata2.api.ep.feed.ODataDeltaFeed;
+import org.apache.olingo.odata2.client.api.ep.DeserializerProperties;
+import org.apache.olingo.odata2.core.edm.EdmDateTimeOffset;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityInfoAggregator;
+import org.apache.olingo.odata2.core.ep.entry.DeletedEntryMetadataImpl;
+import org.apache.olingo.odata2.core.ep.feed.FeedMetadataImpl;
+import org.apache.olingo.odata2.core.ep.feed.ODataDeltaFeedImpl;
+import org.apache.olingo.odata2.core.ep.util.FormatXml;
+
+/**
+ * Atom/XML format reader/consumer for feeds.
+ * 
+ * {@link XmlFeedDeserializer} instance use
+ * {@link XmlEntryDeserializer#readEntry(XMLStreamReader, EntityInfoAggregator, EntityProviderReadProperties)} for
+ * read/consume of several entries.
+ * 
+ * 
+ */
+public class XmlFeedDeserializer {
+
+  /**
+   * 
+   * @param reader
+   * @param eia
+   * @param readProperties
+   * @return {@link ODataDeltaFeed} object
+   * @throws EntityProviderException
+   */
+  public ODataDeltaFeed readFeed(final XMLStreamReader reader, final EntityInfoAggregator eia,
+      final DeserializerProperties readProperties) throws EntityProviderException {
+    try {
+      // read xml tag
+      reader.require(XMLStreamConstants.START_DOCUMENT, null, null);
+      reader.nextTag();
+
+      // read feed tag
+      reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_ATOM_2005, FormatXml.ATOM_FEED);
+      Map<String, String> foundPrefix2NamespaceUri = extractNamespacesFromTag(reader);
+      foundPrefix2NamespaceUri.putAll(readProperties.getValidatedPrefixNamespaceUris());
+      checkAllMandatoryNamespacesAvailable(foundPrefix2NamespaceUri);
+      DeserializerProperties entryReadProperties =
+          DeserializerProperties.initFrom(readProperties)
+          .addValidatedPrefixes(foundPrefix2NamespaceUri).build();
+
+      // read feed data (metadata and entries)
+      return readFeedData(reader, eia, entryReadProperties);
+    } catch (XMLStreamException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass()
+          .getSimpleName()), e);
+    }
+  }
+
+  /**
+   * Read all feed specific data (like <code>inline count</code> and <code>next link</code>) as well as all feed entries
+   * (<code>entry</code>) and delta feed extensions (tombstones).
+   * 
+   * @param reader xml stream reader with xml content to be read
+   * @param eia entity infos for validation and mapping
+   * @param entryReadProperties properties which are used for read of feed.
+   * @return all feed specific data (like <code>inline count</code> and <code>next link</code>) as well as all feed
+   * entries (<code>entry</code>).
+   * @throws XMLStreamException if malformed xml is read in stream
+   * @throws EntityProviderException if xml contains invalid data (based on odata specification and edm definition)
+   */
+  private ODataDeltaFeed readFeedData(final XMLStreamReader reader, final EntityInfoAggregator eia,
+      final DeserializerProperties entryReadProperties) throws XMLStreamException, EntityProviderException {
+    FeedMetadataImpl metadata = new FeedMetadataImpl();
+    XmlEntryDeserializer xec = new XmlEntryDeserializer();
+    List<ODataEntry> results = new ArrayList<ODataEntry>();
+    List<DeletedEntryMetadata> deletedEntries = new ArrayList<DeletedEntryMetadata>();
+
+    while (reader.hasNext() && !isFeedEndTag(reader)) {
+      if (FormatXml.ATOM_ENTRY.equals(reader.getLocalName())) {
+        ODataEntry entry = xec.readEntry(reader, eia, entryReadProperties, true);
+        results.add(entry);
+      } else if (FormatXml.ATOM_TOMBSTONE_DELETED_ENTRY.equals(reader.getLocalName())) {
+        reader.require(XMLStreamConstants.START_ELEMENT, FormatXml.ATOM_TOMBSTONE_NAMESPACE,
+            FormatXml.ATOM_TOMBSTONE_DELETED_ENTRY);
+
+        DeletedEntryMetadataImpl deletedEntryMetadata = readDeletedEntryMetadata(reader);
+        deletedEntries.add(deletedEntryMetadata);
+        reader.next();
+      } else if (FormatXml.M_COUNT.equals(reader.getLocalName())) {
+        reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_M_2007_08, FormatXml.M_COUNT);
+        readInlineCount(reader, metadata);
+      } else if (FormatXml.ATOM_LINK.equals(reader.getLocalName())) {
+        reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_ATOM_2005, FormatXml.ATOM_LINK);
+
+        final String rel = reader.getAttributeValue(null, FormatXml.ATOM_REL);
+        if (FormatXml.ATOM_NEXT_LINK.equals(rel)) {
+          final String uri = reader.getAttributeValue(null, FormatXml.ATOM_HREF);
+          metadata.setNextLink(uri);
+        } else if (FormatXml.ATOM_DELTA_LINK.equals(rel)) {
+          final String uri = reader.getAttributeValue(null, FormatXml.ATOM_HREF);
+          metadata.setDeltaLink(uri);
+        }
+        reader.next();
+      } else {
+        reader.next();
+      }
+      readTillNextStartTag(reader);
+    }
+    return new ODataDeltaFeedImpl(results, metadata, deletedEntries);
+  }
+
+  private DeletedEntryMetadataImpl readDeletedEntryMetadata(final XMLStreamReader reader)
+      throws EntityProviderException {
+    try {
+      DeletedEntryMetadataImpl deletedEntryMetadata = new DeletedEntryMetadataImpl();
+
+      String uri = reader.getAttributeValue(null, FormatXml.ATOM_TOMBSTONE_REF);
+      String whenStr = reader.getAttributeValue(null, FormatXml.ATOM_TOMBSTONE_WHEN);
+      Date when;
+      when = EdmDateTimeOffset.getInstance().valueOfString(whenStr, EdmLiteralKind.DEFAULT, null,
+          Date.class);
+
+      deletedEntryMetadata.setUri(uri);
+      deletedEntryMetadata.setWhen(when);
+      return deletedEntryMetadata;
+    } catch (EdmSimpleTypeException e) {
+      throw new EntityProviderException(EntityProviderException.INVALID_DELETED_ENTRY_METADATA, e);
+    }
+  }
+
+  private void readInlineCount(final XMLStreamReader reader, final FeedMetadataImpl metadata)
+      throws XMLStreamException,
+      EntityProviderException {
+    String inlineCountString = reader.getElementText();
+    if (inlineCountString != null) {
+      try {
+        int inlineCountNumber = Integer.parseInt(inlineCountString);
+        if (inlineCountNumber >= 0) {
+          metadata.setInlineCount(inlineCountNumber);
+        } else {
+          throw new EntityProviderException(EntityProviderException.INLINECOUNT_INVALID
+              .addContent(inlineCountNumber));
+        }
+      } catch (NumberFormatException e) {
+        throw new EntityProviderException(EntityProviderException.INLINECOUNT_INVALID.addContent(""), e);
+      }
+    }
+  }
+
+  private void readTillNextStartTag(final XMLStreamReader reader) throws XMLStreamException {
+    while (reader.hasNext() && !reader.isStartElement()) {
+      reader.next();
+    }
+  }
+
+  private boolean isFeedEndTag(final XMLStreamReader reader) {
+    return reader.isEndElement()
+        && Edm.NAMESPACE_ATOM_2005.equals(reader.getNamespaceURI())
+        && FormatXml.ATOM_FEED.equals(reader.getLocalName());
+  }
+
+  /**
+   * Maps all all found namespaces of current xml tag into a map.
+   * 
+   * @param reader xml reader with current position at a xml tag
+   * @return map with all found namespaces of current xml tag
+   */
+  private Map<String, String> extractNamespacesFromTag(final XMLStreamReader reader) {
+    // collect namespaces
+    Map<String, String> foundPrefix2NamespaceUri = new HashMap<String, String>();
+    int namespaceCount = reader.getNamespaceCount();
+    for (int i = 0; i < namespaceCount; i++) {
+      String namespacePrefix = reader.getNamespacePrefix(i);
+      String namespaceUri = reader.getNamespaceURI(i);
+
+      foundPrefix2NamespaceUri.put(namespacePrefix, namespaceUri);
+    }
+    return foundPrefix2NamespaceUri;
+  }
+
+  /**
+   * 
+   * @param foundPrefix2NamespaceUri
+   * @throws EntityProviderException
+   */
+  private void checkAllMandatoryNamespacesAvailable(final Map<String, String> foundPrefix2NamespaceUri)
+      throws EntityProviderException {
+    if (!foundPrefix2NamespaceUri.containsValue(Edm.NAMESPACE_D_2007_08)) {
+      throw new EntityProviderException(EntityProviderException.INVALID_NAMESPACE.addContent(Edm.NAMESPACE_D_2007_08));
+    } else if (!foundPrefix2NamespaceUri.containsValue(Edm.NAMESPACE_M_2007_08)) {
+      throw new EntityProviderException(EntityProviderException.INVALID_NAMESPACE.addContent(Edm.NAMESPACE_M_2007_08));
+    } else if (!foundPrefix2NamespaceUri.containsValue(Edm.NAMESPACE_ATOM_2005)) {
+      throw new EntityProviderException(EntityProviderException.INVALID_NAMESPACE.addContent(Edm.NAMESPACE_ATOM_2005));
+    }
+  }
+}


[16/24] olingo-odata2 git commit: [OLINGO-1253]Client Module for Olingo v2

Posted by ar...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/ProducerConsumerIntegrationTest.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/ProducerConsumerIntegrationTest.java b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/ProducerConsumerIntegrationTest.java
new file mode 100644
index 0000000..9615caa
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/ProducerConsumerIntegrationTest.java
@@ -0,0 +1,811 @@
+/*******************************************************************************
+ * 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.client.core.ep;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.apache.olingo.odata2.api.batch.BatchException;
+import org.apache.olingo.odata2.api.batch.BatchResponsePart;
+import org.apache.olingo.odata2.api.client.batch.BatchChangeSet;
+import org.apache.olingo.odata2.api.client.batch.BatchChangeSetPart;
+import org.apache.olingo.odata2.api.client.batch.BatchPart;
+import org.apache.olingo.odata2.api.client.batch.BatchSingleResponse;
+import org.apache.olingo.odata2.api.commons.HttpStatusCodes;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmFunctionImport;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.ep.entry.ODataEntry;
+import org.apache.olingo.odata2.api.ep.feed.ODataDeltaFeed;
+import org.apache.olingo.odata2.api.ep.feed.ODataFeed;
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.api.processor.ODataResponse;
+import org.apache.olingo.odata2.client.api.ODataClient;
+import org.apache.olingo.odata2.client.api.ep.DeserializerProperties;
+import org.apache.olingo.odata2.client.api.ep.Entity;
+import org.apache.olingo.odata2.client.api.ep.EntityCollection;
+import org.apache.olingo.odata2.client.api.ep.EntityCollectionSerializerProperties;
+import org.apache.olingo.odata2.client.api.ep.EntitySerializerProperties;
+import org.apache.olingo.odata2.client.api.ep.EntityStream;
+import org.apache.olingo.odata2.core.batch.v2.BatchLineReader;
+import org.apache.olingo.odata2.core.batch.v2.BatchParser;
+import org.apache.olingo.odata2.core.batch.v2.Line;
+import org.apache.olingo.odata2.testutil.mock.MockFacade;
+import org.junit.Test;
+
+public class ProducerConsumerIntegrationTest {
+  protected static final URI BASE_URI;
+  private static final String PUT = "PUT";
+  private static final String BOUNDARY = "batch_123";
+  private static final Object CRLF = "\r\n";
+
+  static {
+    try {
+      BASE_URI = new URI("http://host:80/service/");
+    } catch (URISyntaxException e) {
+      throw new RuntimeException(e);
+    }
+  }
+  private static final DeserializerProperties DEFAULT_READ_PROPERTIES 
+  = DeserializerProperties.init()
+      .build();
+  private static final EntitySerializerProperties DEFAULT_WRITE_PROPERTIES 
+  = EntitySerializerProperties
+      .serviceRoot(
+          BASE_URI).build();
+  private static final String XML = "application/xml";
+  private static final String JSON = "application/json";
+
+  @Test
+  public void produceRoomAndThenConsumeIt() throws Exception {
+    EdmEntitySet roomSet = MockFacade.getMockEdm()
+        .getDefaultEntityContainer().getEntitySet("Rooms");
+    Entity localRoomData = new Entity();
+    localRoomData.addProperty("Id", "1");
+    localRoomData.addProperty("Name", "Neu \n Schwanstein蝴蝶");
+
+    Map<String, Object> properties = execute(localRoomData, roomSet, XML);
+    assertEquals("1", properties.get("Id"));
+    assertEquals("Neu \n Schwanstein蝴蝶", properties.get("Name"));
+
+    Map<String, Object> properties2 = execute(localRoomData, roomSet, JSON);
+    assertEquals("1", properties2.get("Id"));
+    assertEquals("Neu \n Schwanstein蝴蝶", properties2.get("Name"));
+  }
+
+  @Test
+  public void produceRoomFeedAndThenConsumeIt() throws Exception {
+    EdmEntitySet roomSet = MockFacade.getMockEdm()
+        .getDefaultEntityContainer().getEntitySet("Rooms");
+    EntityCollection roomsData = new EntityCollection();
+    Entity localRoomData = new Entity();
+    localRoomData.addProperty("Id", "1");
+    localRoomData.addProperty("Name", "Neu \n Schwanstein蝴蝶");
+    roomsData.addEntity(localRoomData);
+
+    localRoomData = new Entity();
+    localRoomData.addProperty("Id", "2");
+    localRoomData.addProperty("Name", "John蝴蝶");
+    roomsData.addEntity(localRoomData);
+    
+    List<Map<String, Object>> entries = execute1(roomsData, roomSet, XML);
+    validateResults(entries);
+    
+    entries = execute1(roomsData, roomSet, JSON);
+    validateResults(entries);
+  }
+  
+  @Test(expected=EntityProviderException.class)
+  public void negativeTests() throws Exception {
+    EdmEntitySet roomSet = MockFacade.getMockEdm()
+        .getDefaultEntityContainer().getEntitySet("Rooms");
+    Entity localRoomData = new Entity();
+    localRoomData.addProperty("Id", "1");
+    localRoomData.addProperty("Name", "Neu \n Schwanstein蝴蝶");
+
+    Map<String, Object> properties = execute(localRoomData, roomSet, "abc");
+    assertEquals("1", properties.get("Id"));
+    assertEquals("Neu \n Schwanstein蝴蝶", properties.get("Name"));   
+  }
+  
+  @Test(expected=EntityProviderException.class)
+  public void negativeTestsDeserializer() throws Exception {
+    EdmEntitySet roomSet = MockFacade.getMockEdm()
+        .getDefaultEntityContainer().getEntitySet("Rooms");
+    Entity localRoomData = new Entity();
+    localRoomData.addProperty("Id", "1");
+    localRoomData.addProperty("Name", "Neu \n Schwanstein蝴蝶");
+
+    Map<String, Object> properties = executeFail(localRoomData, roomSet, "abc");
+    assertEquals("1", properties.get("Id"));
+    assertEquals("Neu \n Schwanstein蝴蝶", properties.get("Name"));   
+  }
+
+  /**
+   * @param entries
+   */
+  private void validateResults(List<Map<String, Object>> entries) {
+    for (Map<String, Object> entryProperties : entries) {
+      for (Entry<String, Object> properties : entryProperties.entrySet()) {
+        if (properties.getKey().equals("Id")) {
+          assertTrue(properties.getValue().toString().contains("1") || 
+              properties.getValue().toString().contains("2"));
+        } else {
+          assertTrue(properties.getValue().toString().contains("Neu \n Schwanstein蝴蝶") || 
+              properties.getValue().toString().contains("John蝴蝶"));
+        }
+      }
+    }
+  }
+  
+  private Map<String, Object> execute(final Entity localRoomData, final EdmEntitySet roomSet,
+      final String contentType)
+      throws ODataException {
+    localRoomData.setWriteProperties(DEFAULT_WRITE_PROPERTIES);
+    ODataResponse response = ODataClient.newInstance().createSerializer(contentType)
+        .writeEntry(roomSet, localRoomData);
+    InputStream content = response.getEntityAsStream();
+    EntityStream entityContent = new EntityStream();
+    entityContent.setReadProperties(DEFAULT_READ_PROPERTIES);
+    entityContent.setContent(content);
+    ODataEntry entry = ODataClient.newInstance()
+        .createDeserializer(contentType).readEntry(roomSet, entityContent);
+    Map<String, Object> properties = entry.getProperties();
+    return properties;
+  }
+  
+  private Map<String, Object> executeFail(final Entity localRoomData, final EdmEntitySet roomSet,
+      final String contentType)
+      throws ODataException {
+    localRoomData.setWriteProperties(DEFAULT_WRITE_PROPERTIES);
+    ODataResponse response = ODataClient.newInstance().createSerializer(XML)
+        .writeEntry(roomSet, localRoomData);
+    InputStream content = response.getEntityAsStream();
+    EntityStream entityContent = new EntityStream();
+    entityContent.setReadProperties(DEFAULT_READ_PROPERTIES);
+    entityContent.setContent(content);
+    ODataEntry entry = ODataClient.newInstance()
+        .createDeserializer(contentType).readEntry(roomSet, entityContent);
+    Map<String, Object> properties = entry.getProperties();
+    return properties;
+  }
+
+  private List<Map<String, Object>> execute1(final EntityCollection localRoomData, final EdmEntitySet roomSet,
+      final String contentType)
+      throws ODataException {
+    List<Map<String, Object>> propertiesList = new ArrayList<Map<String,Object>>();
+    localRoomData.setCollectionProperties(EntityCollectionSerializerProperties.serviceRoot(BASE_URI).build());
+    ODataResponse response = ODataClient.newInstance().createSerializer(contentType)
+        .writeFeed(roomSet, localRoomData);
+    InputStream content = response.getEntityAsStream();
+    EntityStream entityContent = new EntityStream();
+    entityContent.setReadProperties(DEFAULT_READ_PROPERTIES);
+    entityContent.setContent(content);
+    ODataFeed feed = ODataClient.newInstance()
+        .createDeserializer(contentType).readFeed(roomSet, entityContent);
+    List<ODataEntry> entries = feed.getEntries();
+    for (ODataEntry entry : entries) {
+      propertiesList.add(entry.getProperties());
+    }
+    return propertiesList;
+  }
+  
+  
+  @Test
+  public void executeWriteBatchRequestJSON() throws IOException, 
+  EntityProviderException, BatchException, URISyntaxException {
+    List<BatchPart> batch = new ArrayList<BatchPart>();
+    Map<String, String> headers = new HashMap<String, String>();
+    headers.put("content-type", "application/json");
+    BatchChangeSetPart request = BatchChangeSetPart.method(PUT)
+        .uri("Employees('2')")
+        .body("{\"Age\":40}")
+        .headers(headers)
+        .contentId("111")
+        .build();
+    BatchChangeSet changeSet = BatchChangeSet.newBuilder().build();
+    changeSet.add(request);
+    batch.add((BatchPart) changeSet);
+
+    InputStream batchRequest = ODataClient.newInstance().createSerializer(JSON).
+        readBatchRequest(batch, BOUNDARY);
+    validateBatchRequest(batchRequest);
+  }
+  
+  private void validateBatchRequest(InputStream batchRequest) throws IOException {
+    BatchLineReader reader =
+        new BatchLineReader(batchRequest);
+    List<Line> lines = reader.toLineList();
+    reader.close();
+    int index = 0;
+     
+    assertTrue(lines.get(index++).toString().startsWith("--batch"));
+    assertTrue(lines.get(index++).toString().startsWith("Content-Type: multipart/mixed; boundary=changeset_"));
+    assertEquals(CRLF, lines.get(index++).toString());
+    assertTrue(lines.get(index++).toString().startsWith("--changeset"));
+    assertEquals("Content-Type: application/http" + CRLF, lines.get(index++).toString());
+    assertEquals("Content-Transfer-Encoding: binary" + CRLF, lines.get(index++).toString());
+    assertEquals("Content-Id: 111" + CRLF, lines.get(index++).toString());
+    assertEquals(CRLF, lines.get(index++).toString());
+    assertEquals("PUT Employees('2') HTTP/1.1" + CRLF, lines.get(index++).toString());
+    assertEquals("Content-Length: 10" + CRLF, lines.get(index++).toString());
+    assertEquals("content-type: application/json" + CRLF, lines.get(index++).toString());
+    assertEquals(CRLF, lines.get(index++).toString());
+    assertEquals("{\"Age\":40}" + CRLF, lines.get(index++).toString());
+    assertTrue(lines.get(index++).toString().startsWith("--changeset"));
+    assertTrue(lines.get(index++).toString().startsWith("--batch"));
+  }
+  
+  @Test
+  public void executeWriteBatchResponseJSON() throws BatchException, EntityProviderException {
+    List<BatchResponsePart> parts = new ArrayList<BatchResponsePart>();
+    ODataResponse response = ODataResponse.entity("Walter Winter")
+        .status(HttpStatusCodes.OK)
+        .contentHeader("application/json")
+        .build();
+    List<ODataResponse> responses = new ArrayList<ODataResponse>(1);
+    responses.add(response);
+    parts.add(BatchResponsePart.responses(responses).changeSet(false).build());
+
+    ODataResponse changeSetResponse = ODataResponse.status(HttpStatusCodes.NO_CONTENT).build();
+    responses = new ArrayList<ODataResponse>(1);
+    responses.add(changeSetResponse);
+    parts.add(BatchResponsePart.responses(responses).changeSet(true).build());
+
+    ODataResponse batchResponse = ODataClient.newInstance().createDeserializer(JSON).writeBatchResponse(parts);
+    assertEquals(202, batchResponse.getStatus().getStatusCode());
+    assertNotNull(batchResponse.getEntity());
+    String body = (String) batchResponse.getEntity();
+
+    assertTrue(body.contains("--batch"));
+    assertTrue(body.contains("--changeset"));
+    assertTrue(body.contains("HTTP/1.1 200 OK"));
+    assertTrue(body.contains("Content-Type: application/http"));
+    assertTrue(body.contains("Content-Transfer-Encoding: binary"));
+    assertTrue(body.contains("Walter Winter"));
+    assertTrue(body.contains("multipart/mixed; boundary=changeset"));
+    assertTrue(body.contains("HTTP/1.1 204 No Content"));
+
+    String contentHeader = batchResponse.getContentHeader();
+    BatchParser parser = new BatchParser(contentHeader, true);
+    List<BatchSingleResponse> result = parser.parseBatchResponse(new ByteArrayInputStream(body.getBytes()));
+    assertEquals(2, result.size());
+  }
+  
+  @Test
+  public void readFunctionImportJOSNSimpleProperty1() throws Exception {
+    final EdmFunctionImport functionImport = MockFacade.getMockEdm().getDefaultEntityContainer()
+        .getFunctionImport("MaximalAge");
+    InputStream content = new ByteArrayInputStream("{\"d\":{\"MaximalAge\":42}}".getBytes("UTF-8"));
+    EntityStream entityStream = new EntityStream();
+    entityStream.setReadProperties(DEFAULT_READ_PROPERTIES);
+    entityStream.setContent(content);    
+    
+    final Object result = executeFunctionImport(functionImport, entityStream, JSON);
+    assertEquals((short) 42, result);
+  }
+  
+  @Test
+  public void readFunctionImportXMLSimpleProperty() throws Exception {
+    final EdmFunctionImport functionImport = MockFacade.getMockEdm().getDefaultEntityContainer()
+        .getFunctionImport("MaximalAge");
+    InputStream content = new ByteArrayInputStream((
+        "<?xml version='1.0' encoding='utf-8'?>"
+        + "<MaximalAge xmlns=\"http://schemas.microsoft.com/ado/2007/08/dataservices\" "
+        + "xmlns:m=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\">"
+        + "42</MaximalAge>").getBytes("UTF-8"));
+    EntityStream entityStream = new EntityStream();
+    entityStream.setReadProperties(DEFAULT_READ_PROPERTIES);
+    entityStream.setContent(content);    
+    
+    final Object result = executeFunctionImport(functionImport, entityStream, XML);
+    assertEquals((short) 42, result);
+  }
+  
+  @Test
+  public void readFunctionImportJOSNSimpleProperty2() throws Exception {
+    final EdmFunctionImport functionImport = MockFacade.getMockEdm().getDefaultEntityContainer()
+        .getFunctionImport("MaximalAge");
+    InputStream content = new ByteArrayInputStream("{\"MaximalAge\":42}".getBytes("UTF-8"));
+    EntityStream entityStream = new EntityStream();
+    entityStream.setReadProperties(DEFAULT_READ_PROPERTIES);
+    entityStream.setContent(content);    
+    
+    final Object result = executeFunctionImport(functionImport, entityStream, JSON);
+    assertEquals((short) 42, result);
+  }
+  
+  @SuppressWarnings("unchecked")
+  @Test
+  public void readFunctionImportJSONCollectionOfComplexProperty1() throws Exception {
+    final EdmFunctionImport functionImport = MockFacade.getMockEdm().getDefaultEntityContainer()
+        .getFunctionImport("AllLocations");
+    InputStream content = new ByteArrayInputStream((
+        "{\"results\": [{\"City\": {\"PostalCode\":\"56\",\"CityName\":\"Bangalore\"},"
+        + "\"Country\": \"India\"}]}").getBytes("UTF-8"));
+    EntityStream entityStream = new EntityStream();
+    entityStream.setReadProperties(DEFAULT_READ_PROPERTIES);
+    entityStream.setContent(content);    
+    
+    final Object result = executeFunctionImport(functionImport, entityStream, JSON);
+    List<Map<String, Object>> res = (List<Map<String, Object>>) result;
+    assertEquals(1, res.size());
+    assertEquals("India", ((HashMap<String, Object>)res.get(0)).get("Country"));
+    assertEquals(2, ((Map<String, Object>)((Map<String, Object>)res.get(0)).get("City")).size());
+  }
+  
+  @SuppressWarnings("unchecked")
+  @Test
+  public void readFunctionImportJSONCollectionOfComplexProperty2() throws Exception {
+    final EdmFunctionImport functionImport = MockFacade.getMockEdm().getDefaultEntityContainer()
+        .getFunctionImport("AllLocations");
+    InputStream content = new ByteArrayInputStream((
+        "{\"d\":{\"results\": [{\"City\": {\"PostalCode\":\"56\",\"CityName\":\"Bangalore\"},"
+        + "\"Country\": \"India\"}]}}").getBytes("UTF-8"));
+    EntityStream entityStream = new EntityStream();
+    entityStream.setReadProperties(DEFAULT_READ_PROPERTIES);
+    entityStream.setContent(content);    
+    
+    final Object result = executeFunctionImport(functionImport, entityStream, JSON);
+    List<Map<String, Object>> res = (List<Map<String, Object>>) result;
+    assertEquals(1, res.size());
+    assertEquals("India", ((HashMap<String, Object>)res.get(0)).get("Country"));
+    assertEquals(2, ((Map<String, Object>)((Map<String, Object>)res.get(0)).get("City")).size());
+  }
+  
+  @SuppressWarnings("unchecked")
+  @Test
+  public void readFunctionImportXMLCollectionOfComplexProperty() throws Exception {
+    final EdmFunctionImport functionImport = MockFacade.getMockEdm().getDefaultEntityContainer()
+        .getFunctionImport("AllLocations");
+    InputStream content = new ByteArrayInputStream((
+        "<?xml version='1.0' encoding='utf-8'?>"
+        + "<AllLocations xmlns=\"http://schemas.microsoft.com/ado/2007/08/dataservices\" "
+        + "xmlns:m=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\">"
+        + "<element m:type=\"RefScenario.c_Location\">"
+        + "<City m:type=\"RefScenario.c_City\">"
+        + "<PostalCode>69124</PostalCode>"
+        + "<CityName>Heidelberg</CityName>"
+        + "</City>"
+        + "<Country>Germany</Country>"
+        + "</element>"
+        + "<element m:type=\"RefScenario.c_Location\">"
+        + "<City m:type=\"RefScenario.c_City\">"
+        + "<PostalCode>69190</PostalCode>"
+        + "<CityName>Walldorf</CityName>"
+        + "</City>"
+        + "<Country>Germany</Country>"
+        + "</element>"
+        + "</AllLocations>").getBytes("UTF-8"));
+    EntityStream entityStream = new EntityStream();
+    entityStream.setReadProperties(DEFAULT_READ_PROPERTIES);
+    entityStream.setContent(content);    
+    
+    final Object result = executeFunctionImport(functionImport, entityStream, XML);
+    List<Map<String, Object>> res = (List<Map<String, Object>>) result;
+    assertEquals(2, res.size());
+    assertEquals("Germany", ((HashMap<String, Object>)res.get(0)).get("Country"));
+    assertEquals(2, ((Map<String, Object>)((Map<String, Object>)res.get(0)).get("City")).size());
+  }
+  
+  @Test
+  public void readFunctionImportJSONSingleEntity1() throws Exception {
+    final EdmFunctionImport functionImport = MockFacade.getMockEdm().getDefaultEntityContainer()
+        .getFunctionImport("OldestEmployee");
+    InputStream content = new ByteArrayInputStream(
+        ("{\"d\": {"
+            + "\"__metadata\": {"
+            + "\"type\": \"RefScenario.Employee\","
+            + "\"content_type\": \"image/jpeg\","
+            + "\"media_src\":\"http://localhost:19000/abc/FunctionImportJsonTest/Employees('3')/$value\","
+            + "\"edit_media\":\"http://localhost:19000/abc/FunctionImportJsonTest/Employees('3')/$value\""
+            + "},"
+            + "\"EmployeeId\": \"3\","
+            + "\"EmployeeName\": \"Jonathan Smith\","
+            + "\"ManagerId\": \"1\","
+            + "\"RoomId\": \"2\","
+            + "\"TeamId\": \"1\","
+            + "\"Location\": {"
+            + "\"__metadata\": {"
+            + "\"type\": \"RefScenario.c_Location\""
+            + "},"
+            + "\"City\": {"
+            + "\"__metadata\": {"
+            + "\"type\": \"RefScenario.c_City\""
+            + "},"
+            + "\"PostalCode\": \"69190\","
+            + "\"CityName\": \"Walldorf\""
+            + "},"
+            + "\"Country\": \"Germany\""
+            + "},"
+            + "\"Age\": 56,"
+            + "\"EntryDate\": null,"
+            + "\"ImageUrl\": \"Employees('3')/$value\","
+            + "\"ne_Manager\": {"
+            + "\"__deferred\": {"
+            + "\"uri\": \"http://localhost:19000/abc/FunctionImportJsonTest/Employees('3')/ne_Manager\""
+            + "}"
+            + "},"
+            + "\"ne_Team\": {"
+            + "\"__deferred\": {"
+            + "\"uri\": \"http://localhost:19000/abc/FunctionImportJsonTest/Employees('3')/ne_Team\""
+            + "}"
+            + "},"
+            + "\"ne_Room\": {"
+            + "\"__deferred\": {"
+            + "\"uri\": \"http://localhost:19000/abc/FunctionImportJsonTest/Employees('3')/ne_Room\""
+            + "}"
+            + "}"
+            + "}"
+            + "}").getBytes("UTF-8"));
+    EntityStream entityStream = new EntityStream();
+    entityStream.setReadProperties(DEFAULT_READ_PROPERTIES);
+    entityStream.setContent(content);    
+    
+    final Object result = executeFunctionImport(functionImport, entityStream, JSON);
+    ODataEntry entry = (ODataEntry) result;
+    assertEquals(9, entry.getProperties().size());
+    assertEquals("3", entry.getProperties().get("EmployeeId"));
+  }
+  
+  @Test
+  public void readFunctionImportXMLSingleEntity() throws Exception {
+    final EdmFunctionImport functionImport = MockFacade.getMockEdm().getDefaultEntityContainer()
+        .getFunctionImport("OldestEmployee");
+    InputStream content = new ByteArrayInputStream(
+        ("<?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:8083/olingo-odata2-ref-web/ReferenceScenarioNonJaxrs.svc/\">"
+            + "<id>"
+            + "http://localhost:8083/olingo-odata2-ref-web/ReferenceScenarioNonJaxrs.svc/Employees('3')"
+            + "</id>"
+            + "<title type=\"text\">Jonathan Smith</title>"
+            + "<updated>2017-10-26T09:06:41.15+05:30</updated>"
+            + "<category term=\"RefScenario.Employee\" "
+            + "scheme=\"http://schemas.microsoft.com/ado/2007/08/dataservices/scheme\"/>"
+            + "<link href=\"Employees('3')\" rel=\"edit\" title=\"Employee\"/>"
+            + "<link href=\"Employees('3')/$value\" rel=\"edit-media\" "
+            + "type=\"image/jpeg\"/><link href=\"Employees('3')/ne_Manager\" "
+            + "rel=\"http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager\" "
+            + "title=\"ne_Manager\" type=\"application/atom+xml;type=entry\"/>"
+            + "<link href=\"Employees('3')/ne_Team\" "
+            + "rel=\"http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team\" "
+            + "title=\"ne_Team\" type=\"application/atom+xml;type=entry\"/>"
+            + "<link href=\"Employees('3')/ne_Room\" "
+            + "rel=\"http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room\" "
+            + "title=\"ne_Room\" type=\"application/atom+xml;type=entry\"/>"
+            + "<content type=\"image/jpeg\" src=\"Employees('3')/$value\"/>"
+            + "<m:properties><d:EmployeeId>3</d:EmployeeId>"
+            + "<d:EmployeeName>Jonathan Smith</d:EmployeeName>"
+            + "<d:ManagerId>1</d:ManagerId><d:RoomId>2</d:RoomId>"
+            + "<d:TeamId>1</d:TeamId><d:Location m:type=\"RefScenario.c_Location\">"
+            + "<d:City m:type=\"RefScenario.c_City\"><d:PostalCode>69190</d:PostalCode>"
+            + "<d:CityName>Walldorf</d:CityName></d:City><d:Country>Germany</d:Country>"
+            + "</d:Location><d:Age>56</d:Age><d:EntryDate m:null=\"true\"/>"
+            + "<d:ImageUrl>Employees('3')/$value</d:ImageUrl>"
+            + "</m:properties></entry>").getBytes("UTF-8"));
+    EntityStream entityStream = new EntityStream();
+    entityStream.setReadProperties(DEFAULT_READ_PROPERTIES);
+    entityStream.setContent(content);    
+    
+    final Object result = executeFunctionImport(functionImport, entityStream, XML);
+    ODataEntry entry = (ODataEntry) result;
+    assertEquals(9, entry.getProperties().size());
+    assertEquals("3", entry.getProperties().get("EmployeeId"));
+    assertEquals("Employees('3')/ne_Manager", entry.getMetadata().getAssociationUris("ne_Manager").get(0));
+    assertEquals("http://localhost:8083/olingo-odata2-ref-web/"
+        + "ReferenceScenarioNonJaxrs.svc/Employees('3')", entry.getMetadata().getId());
+  }
+  
+  @Test
+  public void readFunctionImportJSONSingleEntity2() throws Exception {
+    final EdmFunctionImport functionImport = MockFacade.getMockEdm().getDefaultEntityContainer()
+        .getFunctionImport("OldestEmployee");
+    InputStream content = new ByteArrayInputStream(
+        ("{"
+            + "\"__metadata\": {"
+            + "\"type\": \"RefScenario.Employee\","
+            + "\"content_type\": \"image/jpeg\","
+            + "\"media_src\":\"http://localhost:19000/abc/FunctionImportJsonTest/Employees('3')/$value\","
+            + "\"edit_media\":\"http://localhost:19000/abc/FunctionImportJsonTest/Employees('3')/$value\""
+            + "},"
+            + "\"EmployeeId\": \"3\","
+            + "\"EmployeeName\": \"Jonathan Smith\","
+            + "\"ManagerId\": \"1\","
+            + "\"RoomId\": \"2\","
+            + "\"TeamId\": \"1\","
+            + "\"Location\": {"
+            + "\"__metadata\": {"
+            + "\"type\": \"RefScenario.c_Location\""
+            + "},"
+            + "\"City\": {"
+            + "\"__metadata\": {"
+            + "\"type\": \"RefScenario.c_City\""
+            + "},"
+            + "\"PostalCode\": \"69190\","
+            + "\"CityName\": \"Walldorf\""
+            + "},"
+            + "\"Country\": \"Germany\""
+            + "},"
+            + "\"Age\": 56,"
+            + "\"EntryDate\": null,"
+            + "\"ImageUrl\": \"Employees('3')/$value\","
+            + "\"ne_Manager\": {"
+            + "\"__deferred\": {"
+            + "\"uri\": \"http://localhost:19000/abc/FunctionImportJsonTest/Employees('3')/ne_Manager\""
+            + "}"
+            + "},"
+            + "\"ne_Team\": {"
+            + "\"__deferred\": {"
+            + "\"uri\": \"http://localhost:19000/abc/FunctionImportJsonTest/Employees('3')/ne_Team\""
+            + "}"
+            + "},"
+            + "\"ne_Room\": {"
+            + "\"__deferred\": {"
+            + "\"uri\": \"http://localhost:19000/abc/FunctionImportJsonTest/Employees('3')/ne_Room\""
+            + "}"
+            + "}"
+            + "}").getBytes("UTF-8"));
+    EntityStream entityStream = new EntityStream();
+    entityStream.setReadProperties(DEFAULT_READ_PROPERTIES);
+    entityStream.setContent(content);    
+    
+    final Object result = executeFunctionImport(functionImport, entityStream, JSON);
+    ODataEntry entry = (ODataEntry) result;
+    assertEquals(9, entry.getProperties().size());
+    assertEquals("3", entry.getProperties().get("EmployeeId"));
+  }
+  
+  @Test
+  public void readMultipleEntityJSONFunctionImport1() throws Exception {
+    final EdmFunctionImport functionImport = MockFacade.getMockEdm().getDefaultEntityContainer()
+        .getFunctionImport("EmployeeSearch");
+    InputStream content = new ByteArrayInputStream(
+        ("{\"d\": {"
+            + "\"results\": [{"
+            + "\"__metadata\": {"
+            + "\"type\": \"RefScenario.Employee\","
+            + "\"content_type\": \"image/jpeg\","
+            + "\"media_src\":\"http://localhost:19000/abc/FunctionImportJsonTest/Employees('3')/$value\","
+            + "\"edit_media\":\"http://localhost:19000/abc/FunctionImportJsonTest/Employees('3')/$value\""
+            + "},"
+            + "\"EmployeeId\": \"3\","
+            + "\"EmployeeName\": \"Jonathan Smith\","
+            + "\"ManagerId\": \"1\","
+            + "\"RoomId\": \"2\","
+            + "\"TeamId\": \"1\","
+            + "\"Location\": {"
+            + "\"__metadata\": {"
+            + "\"type\": \"RefScenario.c_Location\""
+            + "},"
+            + "\"City\": {"
+            + "\"__metadata\": {"
+            + "\"type\": \"RefScenario.c_City\""
+            + "},"
+            + "\"PostalCode\": \"69190\","
+            + "\"CityName\": \"Walldorf\""
+            + "},"
+            + "\"Country\": \"Germany\""
+            + "},"
+            + "\"Age\": 56,"
+            + "\"EntryDate\": null,"
+            + "\"ImageUrl\": \"Employees('3')/$value\","
+            + "\"ne_Manager\": {"
+            + "\"__deferred\": {"
+            + "\"uri\": \"http://localhost:19000/abc/FunctionImportJsonTest/Employees('3')/ne_Manager\""
+            + "}"
+            + "},"
+            + "\"ne_Team\": {"
+            + "\"__deferred\": {"
+            + "\"uri\": \"http://localhost:19000/abc/FunctionImportJsonTest/Employees('3')/ne_Team\""
+            + "}"
+            + "},"
+            + "\"ne_Room\": {"
+            + "\"__deferred\": {"
+            + "\"uri\": \"http://localhost:19000/abc/FunctionImportJsonTest/Employees('3')/ne_Room\""
+            + "}"
+            + "}"
+            + "}]"
+            + "}"
+            + "}").getBytes("UTF-8"));
+    EntityStream entityStream = new EntityStream();
+    entityStream.setReadProperties(DEFAULT_READ_PROPERTIES);
+    entityStream.setContent(content);
+    final Object result = executeFunctionImport(functionImport, entityStream, JSON);
+    ODataDeltaFeed feed = (ODataDeltaFeed) result;
+    List<ODataEntry> entries = feed.getEntries();
+    int size = entries.size();
+    assertEquals(1, size);
+    String id = (String) entries.get(0).getProperties().get("EmployeeId");
+    assertEquals("3", id);
+  }
+  
+  @Test
+  public void readMultipleEntityJSONFunctionImport2() throws Exception {
+    final EdmFunctionImport functionImport = MockFacade.getMockEdm().getDefaultEntityContainer()
+        .getFunctionImport("EmployeeSearch");
+    InputStream content = new ByteArrayInputStream(
+        ("{"
+            + "\"results\": [{"
+            + "\"__metadata\": {"
+            + "\"type\": \"RefScenario.Employee\","
+            + "\"content_type\": \"image/jpeg\","
+            + "\"media_src\":\"http://localhost:19000/abc/FunctionImportJsonTest/Employees('3')/$value\","
+            + "\"edit_media\":\"http://localhost:19000/abc/FunctionImportJsonTest/Employees('3')/$value\""
+            + "},"
+            + "\"EmployeeId\": \"3\","
+            + "\"EmployeeName\": \"Jonathan Smith\","
+            + "\"ManagerId\": \"1\","
+            + "\"RoomId\": \"2\","
+            + "\"TeamId\": \"1\","
+            + "\"Location\": {"
+            + "\"__metadata\": {"
+            + "\"type\": \"RefScenario.c_Location\""
+            + "},"
+            + "\"City\": {"
+            + "\"__metadata\": {"
+            + "\"type\": \"RefScenario.c_City\""
+            + "},"
+            + "\"PostalCode\": \"69190\","
+            + "\"CityName\": \"Walldorf\""
+            + "},"
+            + "\"Country\": \"Germany\""
+            + "},"
+            + "\"Age\": 56,"
+            + "\"EntryDate\": null,"
+            + "\"ImageUrl\": \"Employees('3')/$value\","
+            + "\"ne_Manager\": {"
+            + "\"__deferred\": {"
+            + "\"uri\": \"http://localhost:19000/abc/FunctionImportJsonTest/Employees('3')/ne_Manager\""
+            + "}"
+            + "},"
+            + "\"ne_Team\": {"
+            + "\"__deferred\": {"
+            + "\"uri\": \"http://localhost:19000/abc/FunctionImportJsonTest/Employees('3')/ne_Team\""
+            + "}"
+            + "},"
+            + "\"ne_Room\": {"
+            + "\"__deferred\": {"
+            + "\"uri\": \"http://localhost:19000/abc/FunctionImportJsonTest/Employees('3')/ne_Room\""
+            + "}"
+            + "}"
+            + "}]"
+            + "}").getBytes("UTF-8"));
+    EntityStream entityStream = new EntityStream();
+    entityStream.setReadProperties(DEFAULT_READ_PROPERTIES);
+    entityStream.setContent(content);
+    final Object result = executeFunctionImport(functionImport, entityStream, JSON);
+    ODataDeltaFeed feed = (ODataDeltaFeed) result;
+    List<ODataEntry> entries = feed.getEntries();
+    int size = entries.size();
+    assertEquals(1, size);
+    String id = (String) entries.get(0).getProperties().get("EmployeeId");
+    assertEquals("3", id);
+  }
+  
+  @SuppressWarnings("unchecked")
+  @Test
+  public void readMultipleEntityXMLFunctionImport() throws Exception {
+    final EdmFunctionImport functionImport = MockFacade.getMockEdm().getDefaultEntityContainer()
+        .getFunctionImport("EmployeeSearch");
+    InputStream content = new ByteArrayInputStream(
+        ("<?xml version='1.0' encoding='utf-8'?>"
+            + "<feed 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:8083/olingo-odata2-ref-web/ReferenceScenarioNonJaxrs.svc/\">"
+            + "<id>http://localhost:8083/olingo-odata2-ref-web/ReferenceScenarioNonJaxrs.svc/Employees</id>"
+            + "<title type=\"text\">Employees</title><updated>2017-10-26T09:17:27.113+05:30</updated>"
+            + "<author><name/></author><link href=\"Employees\" rel=\"self\" title=\"Employees\"/>"
+            + "<entry>"
+            + "<id>http://localhost:8083/olingo-odata2-ref-web/ReferenceScenarioNonJaxrs.svc/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=\"image/jpeg\"/>"
+            + "<link href=\"Employees('1')/ne_Manager\" "
+            + "rel=\"http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager\" "
+            + "title=\"ne_Manager\" type=\"application/atom+xml;type=entry\"/>"
+            + "<link href=\"Employees('1')/ne_Team\" "
+            + "rel=\"http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team\" "
+            + "title=\"ne_Team\" type=\"application/atom+xml;type=entry\"/>"
+            + "<link href=\"Employees('1')/ne_Room\" "
+            + "rel=\"http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room\" "
+            + "title=\"ne_Room\" type=\"application/atom+xml;type=entry\"/>"
+            + "<content type=\"image/jpeg\" 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:City m:type=\"RefScenario.c_City\">"
+            + "</d:City>"
+            + "<d:Country>Germany</d:Country></d:Location><d:Age>52</d:Age>"
+            + "<d:EntryDate>1999-01-01T00:00:00</d:EntryDate>"
+            + "<d:ImageUrl>Employees('1')/$value</d:ImageUrl>"
+            + "</m:properties></entry>"
+            + "<entry>"
+            + "<id>http://localhost:8083/olingo-odata2-ref-web/ReferenceScenarioNonJaxrs.svc/Employees('2')</id>"
+            + "<title type=\"text\">Frederic Fall</title>"
+            + "<updated>2003-07-01T00:00:00Z</updated>"
+            + "<category term=\"RefScenario.Employee\" "
+            + "scheme=\"http://schemas.microsoft.com/ado/2007/08/dataservices/scheme\"/>"
+            + "<link href=\"Employees('2')\" rel=\"edit\" title=\"Employee\"/>"
+            + "<link href=\"Employees('2')/$value\" rel=\"edit-media\" "
+            + "type=\"image/jpeg\"/><link href=\"Employees('2')/ne_Manager\" "
+            + "rel=\"http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager\" "
+            + "title=\"ne_Manager\" type=\"application/atom+xml;type=entry\"/>"
+            + "<link href=\"Employees('2')/ne_Team\" "
+            + "rel=\"http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team\" "
+            + "title=\"ne_Team\" type=\"application/atom+xml;type=entry\"/>"
+            + "<link href=\"Employees('2')/ne_Room\" "
+            + "rel=\"http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room\" "
+            + "title=\"ne_Room\" type=\"application/atom+xml;type=entry\"/>"
+            + "<content type=\"image/jpeg\" src=\"Employees('2')/$value\"/>"
+            + "<m:properties><d:EmployeeId>2</d:EmployeeId>"
+            + "<d:EmployeeName>Frederic Fall</d:EmployeeName>"
+            + "<d:ManagerId>1</d:ManagerId><d:RoomId>2</d:RoomId>"
+            + "<d:TeamId>1</d:TeamId>"
+            + "<d:Location m:type=\"RefScenario.c_Location\" m:null=\"true\">"
+            + "</d:Location><d:Age>32</d:Age>"
+            + "<d:EntryDate>2003-07-01T00:00:00</d:EntryDate>"
+            + "</m:properties></entry></feed>").getBytes("UTF-8"));
+    EntityStream entityStream = new EntityStream();
+    entityStream.setReadProperties(DEFAULT_READ_PROPERTIES);
+    entityStream.setContent(content);
+    final Object result = executeFunctionImport(functionImport, entityStream, XML);
+    ODataDeltaFeed feed = (ODataDeltaFeed) result;
+    List<ODataEntry> entries = feed.getEntries();
+    int size = entries.size();
+    assertEquals(2, size);
+    assertEquals(9, entries.get(0).getProperties().size());
+    assertEquals(8, entries.get(1).getProperties().size());
+    assertEquals(0, ((Map<String, Object>)
+        ((Map<String, Object>)entries.get(0).getProperties().get("Location")).get("City")).size());
+    assertEquals(null, entries.get(1).getProperties().get("Location"));
+    String id = (String) entries.get(0).getProperties().get("EmployeeId");
+    assertEquals("1", id);
+  }
+
+  /**
+   * @param functionImport
+   * @param entityStream
+   * @return
+   * @throws EntityProviderException
+   */
+  private Object executeFunctionImport(final EdmFunctionImport functionImport, 
+      EntityStream entityStream, String contentType)
+      throws EntityProviderException {
+    return ODataClient.newInstance().
+        createDeserializer(contentType).readFunctionImport(functionImport, entityStream);
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/SerializerPropertiesTest.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/SerializerPropertiesTest.java b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/SerializerPropertiesTest.java
new file mode 100644
index 0000000..32ec72c
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/SerializerPropertiesTest.java
@@ -0,0 +1,87 @@
+/*******************************************************************************
+ * 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.client.core.ep;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.net.URI;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.olingo.odata2.client.api.ep.EntityCollectionSerializerProperties;
+import org.apache.olingo.odata2.client.api.ep.EntitySerializerProperties;
+import org.apache.olingo.odata2.testutil.fit.BaseTest;
+import org.junit.Test;
+
+/**
+ *  
+ */
+public class SerializerPropertiesTest extends BaseTest {
+
+  @Test
+  public void buildFeedProperties() throws Exception {
+    URI serviceRoot = new URI("http://localhost:80/");
+    EntitySerializerProperties properties = EntitySerializerProperties.serviceRoot(serviceRoot)
+        .build();
+
+    assertEquals("Wrong base uri.", "http://localhost:80/", properties.getServiceRoot().toASCIIString());
+   }
+
+  @Test
+  public void buildPropertiesDefault() throws Exception {
+    URI serviceRoot = new URI("http://localhost:80/");
+    final EntitySerializerProperties properties 
+    = EntitySerializerProperties.serviceRoot(serviceRoot).build();
+
+    assertFalse(properties.isIncludeMetadata());
+    assertTrue(properties.isValidatingFacets());
+  }
+
+  @Test
+  public void buildPropertiesAllSet() throws Exception {
+    URI serviceRoot = new URI("http://localhost:80/");
+    Map<String, Map<String, Object>> links = new HashMap<String, Map<String, Object>>();
+    links.put("aNavigationProperty", Collections.<String, Object> emptyMap());
+    final EntitySerializerProperties properties = EntitySerializerProperties
+        .serviceRoot(serviceRoot)
+        .includeMetadata(true)
+        .validatingFacets(false)
+        .build();
+
+    assertEquals("Wrong base uri.", "http://localhost:80/", properties.getServiceRoot().toASCIIString());
+    assertTrue("Metadata in content should be set", properties.isIncludeMetadata());
+    assertFalse("validating facets should be not set", properties.isValidatingFacets());
+  }
+
+  @Test
+  public void buildPropertiesForEntityCollectionAllSet() throws Exception {
+    URI serviceRoot = new URI("http://localhost:80/");
+    URI selfLink = new URI("http://some.uri");
+    final EntityCollectionSerializerProperties properties = 
+        EntityCollectionSerializerProperties.serviceRoot(serviceRoot)
+        .selfLink(selfLink)
+        .build();
+
+    assertEquals("Wrong base uri.", "http://localhost:80/", properties.getServiceRoot().toASCIIString());
+    assertEquals(selfLink, properties.getSelfLink());
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/deserializer/AbstractDeserializerTest.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/deserializer/AbstractDeserializerTest.java b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/deserializer/AbstractDeserializerTest.java
new file mode 100644
index 0000000..df82949
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/deserializer/AbstractDeserializerTest.java
@@ -0,0 +1,182 @@
+/*******************************************************************************
+ * 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.client.core.ep.deserializer;
+
+import static org.junit.Assert.assertNotNull;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.StringReader;
+import java.io.UnsupportedEncodingException;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.ep.entry.ODataEntry;
+import org.apache.olingo.odata2.api.ep.feed.ODataFeed;
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.client.api.ep.DeserializerProperties;
+import org.apache.olingo.odata2.client.api.ep.EntityStream;
+import org.apache.olingo.odata2.testutil.fit.BaseTest;
+import org.apache.olingo.odata2.testutil.mock.MockFacade;
+
+/**
+ *  
+ */
+public abstract class AbstractDeserializerTest extends BaseTest {
+
+  protected static final DeserializerProperties DEFAULT_PROPERTIES = DeserializerProperties.init()
+      .build();
+
+  protected XMLStreamReader createReaderForTest(final String input) throws XMLStreamException {
+    return createReaderForTest(input, false);
+  }
+
+  protected XMLStreamReader createReaderForTest(final String input, final boolean namespaceAware)
+      throws XMLStreamException {
+    XMLInputFactory factory = XMLInputFactory.newInstance();
+    factory.setProperty(XMLInputFactory.IS_VALIDATING, false);
+    factory.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, namespaceAware);
+
+    XMLStreamReader streamReader = factory.createXMLStreamReader(new StringReader(input));
+
+    return streamReader;
+  }
+
+  protected Map<String, Object> createTypeMappings(final String key, final Object value) {
+    Map<String, Object> typeMappings = new HashMap<String, Object>();
+    typeMappings.put(key, value);
+    return typeMappings;
+  }
+
+  protected InputStream getFileAsStream(final String filename) throws IOException {
+    InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream(filename);
+    if (in == null) {
+      throw new IOException("Requested file '" + filename + "' was not found.");
+    }
+    return in;
+  }
+
+  protected String readFile(final String filename) throws IOException {
+    InputStream in = getFileAsStream(filename);
+
+    byte[] tmp = new byte[8192];
+    int count = in.read(tmp);
+    StringBuilder b = new StringBuilder();
+    while (count >= 0) {
+      b.append(new String(tmp, 0, count));
+      count = in.read(tmp);
+    }
+
+    return b.toString();
+  }
+
+  /**
+   * Create a map with a 'String' to 'Class<?>' mapping based on given parameters.
+   * Therefore parameters MUST be a set of such pairs.
+   * As example an correct method call would be:
+   * <p>
+   * <code>
+   * createTypeMappings("someKey", Integer.class, "anotherKey", Long.class);
+   * </code>
+   * </p>
+   * 
+   * @param firstKeyThenMappingClass
+   * @return
+   */
+  protected Map<String, Object> createTypeMappings(final Object... firstKeyThenMappingClass) {
+    Map<String, Object> typeMappings = new HashMap<String, Object>();
+    if (firstKeyThenMappingClass.length % 2 != 0) {
+      throw new IllegalArgumentException("Got odd number of parameters. Please read javadoc.");
+    }
+    for (int i = 0; i < firstKeyThenMappingClass.length; i += 2) {
+      String key = (String) firstKeyThenMappingClass[i];
+      Class<?> mappingClass = (Class<?>) firstKeyThenMappingClass[i + 1];
+      typeMappings.put(key, mappingClass);
+    }
+    return typeMappings;
+  }
+
+  protected InputStream createContentAsStream(final String content) throws UnsupportedEncodingException {
+    return new ByteArrayInputStream(content.getBytes("UTF-8"));
+  }
+
+  /**
+   * 
+   * @param content
+   * @param replaceWhitespaces if <code>true</code> all XML not necessary whitespaces between tags are
+   * @return
+   * @throws UnsupportedEncodingException
+   */
+  protected InputStream createContentAsStream(final String content, final boolean replaceWhitespaces)
+      throws UnsupportedEncodingException {
+    String contentForStream = content;
+    if (replaceWhitespaces) {
+      contentForStream = content.replaceAll(">\\s.<", "><");
+    }
+
+    return new ByteArrayInputStream(contentForStream.getBytes("UTF-8"));
+  }
+
+  protected ODataEntry prepareAndExecuteEntry(final String fileName, final String entitySetName,
+      final DeserializerProperties readProperties) throws IOException, EdmException, ODataException,
+      UnsupportedEncodingException, EntityProviderException {
+    // prepare
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet(entitySetName);
+    String content = readFile(fileName);
+    assertNotNull(content);
+    InputStream contentBody = createContentAsStream(content);
+    EntityStream entityStream = new EntityStream();
+    entityStream.setContent(contentBody);
+    entityStream.setReadProperties(readProperties);
+
+    // execute
+    JsonEntityDeserializer xec = new JsonEntityDeserializer();
+    ODataEntry result = xec.readEntry(entitySet, entityStream);
+    assertNotNull(result);
+    return result;
+  }
+
+  protected ODataFeed prepareAndExecuteFeed(final String fileName, final String entitySetName,
+      final DeserializerProperties readProperties) throws IOException, EdmException, ODataException,
+      UnsupportedEncodingException, EntityProviderException {
+    // prepare
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet(entitySetName);
+    String content = readFile(fileName);
+    assertNotNull(content);
+    InputStream contentBody = createContentAsStream(content);
+    EntityStream entityStream = new EntityStream();
+    entityStream.setContent(contentBody);
+    entityStream.setReadProperties(readProperties);
+
+    // execute
+    JsonEntityDeserializer xec = new JsonEntityDeserializer();
+    ODataFeed result = xec.readFeed(entitySet, entityStream);
+    assertNotNull(result);
+    return result;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/deserializer/AbstractXmlDeserializerTest.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/deserializer/AbstractXmlDeserializerTest.java b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/deserializer/AbstractXmlDeserializerTest.java
new file mode 100644
index 0000000..bfd3c6c
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/deserializer/AbstractXmlDeserializerTest.java
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * 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.client.core.ep.deserializer;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public abstract class AbstractXmlDeserializerTest extends AbstractDeserializerTest {
+
+  public enum StreamWriterImplType {
+    WOODSTOCKIMPL, SUNINTERNALIMPL;
+  }
+
+  // CHECKSTYLE:OFF
+  public AbstractXmlDeserializerTest(final StreamWriterImplType type) {
+    switch (type) {
+    case WOODSTOCKIMPL:
+      System.setProperty("javax.xml.stream.XMLInputFactory", "com.ctc.wstx.stax.WstxInputFactory"); // NOSONAR
+      System.setProperty("javax.xml.stream.XMLOutputFactory", "com.ctc.wstx.stax.WstxOutputFactory"); // NOSONAR
+      break;
+    case SUNINTERNALIMPL:
+      System.setProperty("javax.xml.stream.XMLInputFactory", "com.sun.xml.internal.stream.XMLInputFactoryImpl"); // NOSONAR
+      System.setProperty("javax.xml.stream.XMLOutputFactory", "com.sun.xml.internal.stream.XMLOutputFactoryImpl"); // NOSONAR
+      break;
+    default:
+      System.setProperty("javax.xml.stream.XMLOutputFactory", "com.sun.xml.internal.stream.XMLOutputFactoryImpl"); // NOSONAR
+      System.setProperty("javax.xml.stream.XMLInputFactory", "com.sun.xml.internal.stream.XMLInputFactoryImpl"); // NOSONAR
+      break;
+    }
+  }
+
+  // CHECKSTYLE:On
+
+  @Parameterized.Parameters
+  public static List<Object[]> data() {
+    // If desired this can be made dependent on runtime variables
+    Object[][] a = new Object[2][1];
+    a[0][0] = StreamWriterImplType.WOODSTOCKIMPL;
+    a[1][0] = StreamWriterImplType.SUNINTERNALIMPL;
+
+    return Arrays.asList(a);
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/deserializer/Callback.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/deserializer/Callback.java b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/deserializer/Callback.java
new file mode 100644
index 0000000..2d1bf91
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/deserializer/Callback.java
@@ -0,0 +1,21 @@
+package org.apache.olingo.odata2.client.core.ep.deserializer;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
+import org.apache.olingo.odata2.api.exception.ODataApplicationException;
+import org.apache.olingo.odata2.client.api.ep.DeserializerProperties;
+import org.apache.olingo.odata2.client.api.ep.callback.OnDeserializeInlineContent;
+
+public class Callback implements OnDeserializeInlineContent {
+
+  @Override
+  public DeserializerProperties receiveReadProperties(DeserializerProperties readProperties,
+      EdmNavigationProperty navigationProperty) throws ODataApplicationException {
+    Map<String, Object> typeMappings = new HashMap<String, Object>();
+    return DeserializerProperties.init().addTypeMappings(typeMappings).
+        callback(new Callback()).build();
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/deserializer/JsonEntryDeepInsertEntryTest.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/deserializer/JsonEntryDeepInsertEntryTest.java b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/deserializer/JsonEntryDeepInsertEntryTest.java
new file mode 100644
index 0000000..d6f25a7
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/deserializer/JsonEntryDeepInsertEntryTest.java
@@ -0,0 +1,168 @@
+/*******************************************************************************
+ * 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.client.core.ep.deserializer;
+
+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 static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
+import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
+import org.apache.olingo.odata2.api.edm.EdmType;
+import org.apache.olingo.odata2.api.edm.EdmTypeKind;
+import org.apache.olingo.odata2.api.ep.entry.ODataEntry;
+import org.apache.olingo.odata2.client.api.ep.DeserializerProperties;
+import org.apache.olingo.odata2.client.api.ep.EntityStream;
+import org.apache.olingo.odata2.client.api.ep.callback.OnDeserializeInlineContent;
+import org.apache.olingo.odata2.testutil.mock.MockFacade;
+import org.junit.Test;
+
+public class JsonEntryDeepInsertEntryTest extends AbstractDeserializerTest {
+
+  private static final String EMPLOYEE_WITH_INLINE_TEAM = "JsonEmployeeWithInlineTeam.json";
+  private static final String INLINE_ROOM_WITH_INLINE_BUILDING = "JsonInlineRoomWithInlineBuilding.json";
+  private static final String INLINE_ROOM_WITH_INLINE_NULL = "JsonInlineRoomWithInlineNull.json";
+
+  @Test
+  public void innerEntryNoMediaResource() throws Exception {
+    ODataEntry outerEntry = prepareAndExecuteEntry(EMPLOYEE_WITH_INLINE_TEAM, "Employees", DEFAULT_PROPERTIES);
+    assertTrue(outerEntry.containsInlineEntry());
+
+    ODataEntry innerTeam = (ODataEntry) outerEntry.getProperties().get("ne_Team");
+    assertNotNull(innerTeam);
+    assertFalse(innerTeam.containsInlineEntry());
+
+    Map<String, Object> innerTeamProperties = innerTeam.getProperties();
+
+    assertEquals("1", innerTeamProperties.get("Id"));
+    assertEquals("Team 1", innerTeamProperties.get("Name"));
+    assertEquals(Boolean.FALSE, innerTeamProperties.get("isScrumTeam"));
+    assertNull(innerTeamProperties.get("nt_Employees"));
+
+    List<String> associationUris = innerTeam.getMetadata().getAssociationUris("nt_Employees");
+    assertEquals(1, associationUris.size());
+    assertEquals("http://localhost:8080/ReferenceScenario.svc/Teams('1')/nt_Employees", associationUris.get(0));
+  }
+
+  @Test
+  public void innerEntryWithOptionalNavigationProperty() throws Exception {
+    // prepare
+    DeserializerProperties readProperties =
+        DeserializerProperties.init().build();
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+    // modify edm for test case (change multiplicity to ZERO_TO_ONE)
+    EdmType navigationType = mock(EdmType.class);
+    when(navigationType.getKind()).thenReturn(EdmTypeKind.ENTITY);
+
+    EdmNavigationProperty navigationProperty = mock(EdmNavigationProperty.class);
+    when(navigationProperty.getName()).thenReturn("ne_Team");
+    when(navigationProperty.getType()).thenReturn(navigationType);
+    when(navigationProperty.getMultiplicity()).thenReturn(EdmMultiplicity.ZERO_TO_ONE);
+
+    when(entitySet.getEntityType().getProperty("ne_Team")).thenReturn(navigationProperty);
+    EdmEntitySet targetEntitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+    when(entitySet.getRelatedEntitySet(navigationProperty)).thenReturn(targetEntitySet);
+
+    // execute
+    JsonEntityDeserializer xec = new JsonEntityDeserializer();
+    InputStream contentBody = getFileAsStream(EMPLOYEE_WITH_INLINE_TEAM);
+    EntityStream entityStream = new EntityStream();
+    entityStream.setContent(contentBody);
+    entityStream.setReadProperties(readProperties);
+    ODataEntry outerEntry = xec.readEntry(entitySet, entityStream);
+
+    ODataEntry innerTeam = (ODataEntry) outerEntry.getProperties().get("ne_Team");
+    Map<String, Object> innerTeamProperties = innerTeam.getProperties();
+
+    assertEquals("1", innerTeamProperties.get("Id"));
+    assertEquals("Team 1", innerTeamProperties.get("Name"));
+    assertEquals(Boolean.FALSE, innerTeamProperties.get("isScrumTeam"));
+    assertNull(innerTeamProperties.get("nt_Employees"));
+
+    List<String> associationUris = innerTeam.getMetadata().getAssociationUris("nt_Employees");
+    assertEquals(1, associationUris.size());
+    assertEquals("http://localhost:8080/ReferenceScenario.svc/Teams('1')/nt_Employees", associationUris.get(0));
+  }
+
+  @Test
+  public void inlineRoomWithInlineBuilding() throws Exception {
+    OnDeserializeInlineContent callback = new Callback();
+    DeserializerProperties readProperties = DeserializerProperties.init().callback(callback).build();
+    ODataEntry outerEntry = prepareAndExecuteEntry(INLINE_ROOM_WITH_INLINE_BUILDING, "Employees", readProperties);
+    assertTrue(outerEntry.containsInlineEntry());
+
+    ODataEntry innerRoom = (ODataEntry) outerEntry.getProperties().get("ne_Room");
+    assertNotNull(innerRoom);
+    assertTrue(innerRoom.containsInlineEntry());
+
+    Map<String, Object> innerRoomProperties = innerRoom.getProperties();
+
+    assertEquals(5, innerRoomProperties.size());
+    assertEquals("1", innerRoomProperties.get("Id"));
+    assertEquals("Room 1", innerRoomProperties.get("Name"));
+    assertEquals(Short.valueOf("1"), innerRoomProperties.get("Version"));
+    assertEquals(Short.valueOf("1"), innerRoomProperties.get("Seats"));
+    assertNull(innerRoomProperties.get("nr_Employees"));
+
+    List<String> associationUris = innerRoom.getMetadata().getAssociationUris("nr_Employees");
+    assertEquals(1, associationUris.size());
+    assertEquals("http://localhost:8080/ReferenceScenario.svc/Rooms('1')/nr_Employees", associationUris.get(0));
+
+    associationUris = innerRoom.getMetadata().getAssociationUris("nr_Building");
+    assertEquals(Collections.emptyList(), associationUris);
+
+    assertEquals("W/\"1\"", innerRoom.getMetadata().getEtag());
+
+    ODataEntry innerBuilding = (ODataEntry) innerRoomProperties.get("nr_Building");
+    assertNotNull(innerBuilding);
+    assertFalse(innerBuilding.containsInlineEntry());
+
+    Map<String, Object> innerBuildingProperties = innerBuilding.getProperties();
+    assertEquals(3, innerBuildingProperties.size());
+    assertEquals("1", innerBuildingProperties.get("Id"));
+    assertEquals("Building 1", innerBuildingProperties.get("Name"));
+    assertEquals(null, innerBuildingProperties.get("Image"));
+    assertNull(innerBuildingProperties.get("nb_Rooms"));
+
+    associationUris = innerBuilding.getMetadata().getAssociationUris("nb_Rooms");
+    assertEquals(1, associationUris.size());
+    assertEquals("http://localhost:8080/ReferenceScenario.svc/Buildings('1')/nb_Rooms", associationUris.get(0));
+  }
+
+  @Test
+  public void inlineRoomWithInlineNull() throws Exception {
+    DeserializerProperties readProperties =
+        DeserializerProperties.init().build();
+    ODataEntry outerEntry = prepareAndExecuteEntry(INLINE_ROOM_WITH_INLINE_NULL, "Employees", readProperties);
+
+    ODataEntry innerRoom = (ODataEntry) outerEntry.getProperties().get("ne_Room");
+    assertNull(innerRoom);
+  }
+  
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/deserializer/JsonEntryDeepInsertFeedTest.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/deserializer/JsonEntryDeepInsertFeedTest.java b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/deserializer/JsonEntryDeepInsertFeedTest.java
new file mode 100644
index 0000000..b1a8d0b
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/deserializer/JsonEntryDeepInsertFeedTest.java
@@ -0,0 +1,154 @@
+/*******************************************************************************
+ * 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.client.core.ep.deserializer;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.io.InputStream;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+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.client.api.ep.EntityStream;
+import org.apache.olingo.odata2.client.core.ep.deserializer.JsonEntityDeserializer;
+import org.apache.olingo.odata2.testutil.mock.MockFacade;
+import org.junit.Test;
+
+/**
+ *  
+ */
+public class JsonEntryDeepInsertFeedTest extends AbstractDeserializerTest {
+
+  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";
+
+  @Test
+  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 innerFeedNoMediaResource() throws Exception {
+    ODataEntry outerEntry = prepareAndExecuteEntry(BUILDING_WITH_INLINE_ROOMS, "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 innerFeedNoMediaResourceContainsNextLinkAndCount() throws Exception {
+    ODataEntry outerEntry =
+        prepareAndExecuteEntry(BUILDING_WITH_INLINE_ROOMS_NEXTLINK_AND_COUNT, "Buildings", DEFAULT_PROPERTIES);
+
+    ODataFeed innerRoomFeed = (ODataFeed) outerEntry.getProperties().get("nb_Rooms");
+    assertNotNull(innerRoomFeed);
+
+    List<ODataEntry> rooms = innerRoomFeed.getEntries();
+    assertNotNull(rooms);
+    assertEquals(1, rooms.size());
+
+    FeedMetadata roomsMetadata = innerRoomFeed.getFeedMetadata();
+    assertEquals(Integer.valueOf(1), roomsMetadata.getInlineCount());
+    assertEquals("nextLink", roomsMetadata.getNextLink());
+  }
+
+  @Test
+  public void innerFeedNoMediaResourceSimpleArray() throws Exception {
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Buildings");
+    String content = "{\"d\":{\"Id\":\"1\",\"Name\":\"Building 1\","
+        + "\"nb_Rooms\":[{\"Id\":\"1\",\"Name\":\"Room 1\"}]}}";
+    InputStream contentBody = createContentAsStream(content);
+    EntityStream entityStream = new EntityStream();
+    entityStream.setContent(contentBody);
+    entityStream.setReadProperties(DEFAULT_PROPERTIES);
+    final ODataEntry outerEntry = new JsonEntityDeserializer().readEntry(entitySet, entityStream);
+    assertNotNull(outerEntry);
+    final ODataFeed innerRoomFeed = (ODataFeed) outerEntry.getProperties().get("nb_Rooms");
+    assertNotNull(innerRoomFeed);
+
+    final List<ODataEntry> rooms = innerRoomFeed.getEntries();
+    assertNotNull(rooms);
+    assertEquals(1, rooms.size());
+  }
+
+  @Test
+  public void innerFeedMediaResource() throws Exception {
+    ODataEntry outerEntry = prepareAndExecuteEntry(TEAM_WITH_INLINE_EMPLOYEES, "Teams", DEFAULT_PROPERTIES);
+
+    ODataFeed innerEmployeeFeed = (ODataFeed) outerEntry.getProperties().get("nt_Employees");
+    assertNotNull(innerEmployeeFeed);
+
+    List<ODataEntry> employees = innerEmployeeFeed.getEntries();
+    assertNotNull(employees);
+    assertEquals(3, employees.size());
+  }
+}


[09/24] olingo-odata2 git commit: [OLINGO-1253]Client Module for Olingo v2

Posted by ar...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/serializer/AtomFeedSerializerTest.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/serializer/AtomFeedSerializerTest.java b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/serializer/AtomFeedSerializerTest.java
new file mode 100644
index 0000000..8ceead5
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/serializer/AtomFeedSerializerTest.java
@@ -0,0 +1,1033 @@
+/*******************************************************************************
+ * 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.client.core.ep.serializer;
+
+import static org.custommonkey.xmlunit.XMLAssert.assertXpathExists;
+import static org.custommonkey.xmlunit.XMLAssert.assertXpathNotExists;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmFacets;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.edm.EdmTyped;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.processor.ODataResponse;
+import org.apache.olingo.odata2.api.uri.info.GetEntitySetUriInfo;
+import org.apache.olingo.odata2.client.api.ep.Entity;
+import org.apache.olingo.odata2.client.api.ep.EntityCollection;
+import org.apache.olingo.odata2.client.api.ep.EntityCollectionSerializerProperties;
+import org.apache.olingo.odata2.client.api.ep.EntitySerializerProperties;
+import org.apache.olingo.odata2.client.core.ep.AbstractProviderTest;
+import org.apache.olingo.odata2.client.core.ep.AtomSerializerDeserializer;
+import org.apache.olingo.odata2.testutil.helper.StringHelper;
+import org.apache.olingo.odata2.testutil.mock.MockFacade;
+import org.custommonkey.xmlunit.exceptions.XpathException;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.xml.sax.SAXException;
+
+/**
+ *  
+ */
+public class AtomFeedSerializerTest extends AbstractProviderTest {
+  @Rule
+  public ExpectedException expectedEx = ExpectedException.none();
+
+  private String employeeXPathString = "/a:entry/a:link[@href=\"Rooms('1')/nr_Employees\" and @title='nr_Employees']";
+
+  private static final String EXP_MSG = "Write properties are mandatory for XML.";
+  private static final String ERROR_MSG = "Entity or expanded entity cannot have null value.";
+  
+  public AtomFeedSerializerTest(final StreamWriterImplType type) {
+    super(type);
+  }
+
+  private GetEntitySetUriInfo view;
+
+  @Before
+  public void before() throws Exception {
+    initializeRoomData(1);
+
+    view = mock(GetEntitySetUriInfo.class);
+
+    EdmEntitySet set = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+    when(view.getTargetEntitySet()).thenReturn(set);
+  }
+
+  @Test
+  public void entityWithInlineFeed() throws Exception {
+    Entity roomData = new Entity();
+    roomData.addProperty("Id", "1");
+    roomData.addProperty("Name", "Neu Schwanstein");
+    roomData.addProperty("Seats", new Integer(20));
+    EntityCollection listData = new EntityCollection();
+    EntitySerializerProperties properties =
+        EntitySerializerProperties.serviceRoot(BASE_URI)
+            .includeMetadata(true).build();
+    Entity data = new Entity();
+    data.addProperty("EmployeeId", "1");
+    data.addProperty("EmployeeName", "EmpName1");
+    data.addProperty("RoomId", "1");
+    listData.addEntity(data);
+    data.setWriteProperties(properties);
+
+    data = new Entity();
+    data.addProperty("EmployeeId", "1");
+    data.addProperty("RoomId", "1");
+    data.setWriteProperties(properties);
+    listData.addEntity(data);
+    EntityCollectionSerializerProperties inlineProperties =
+        EntityCollectionSerializerProperties.serviceRoot(BASE_URI).build();
+
+    listData.setCollectionProperties(inlineProperties);
+    AtomSerializerDeserializer provider = createAtomEntityProvider();
+    roomData.addNavigation("nr_Employees", listData);
+    roomData.setWriteProperties(properties);
+    ODataResponse response =
+        provider.writeEntry(MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms"), roomData);
+
+    String xmlString = verifyResponse(response);
+    assertXpathNotExists("/a:entry/m:properties", xmlString);
+    assertXpathExists("/a:entry/a:link", xmlString);
+    verifyEmployees(employeeXPathString, xmlString);
+  }
+
+  public void entityWithPartialInlineFeed() throws Exception {
+    expectedEx.expect(EntityProviderException.class);
+    expectedEx.expectMessage("Entity or expanded entity cannot have null value.");
+    Entity roomData = new Entity();
+    roomData.addProperty("Id", "1");
+    roomData.addProperty("Name", "Neu Schwanstein");
+    roomData.addProperty("Seats", new Integer(20));
+    EntityCollection listData = new EntityCollection();
+    EntitySerializerProperties properties =
+        EntitySerializerProperties.serviceRoot(BASE_URI)
+            .includeMetadata(true).build();
+    Entity data = new Entity();
+    data.addProperty("EmployeeId", "1");
+    data.addProperty("EmployeeName", "EmpName1");
+    data.addProperty("RoomId", "1");
+    listData.addEntity(data);
+    data.setWriteProperties(properties);
+
+    data = new Entity();
+    data.addProperty("EmployeeId", "1");
+    data.addProperty("RoomId", "1");
+    data.setWriteProperties(properties);
+    listData.addEntity(data);
+
+    data = new Entity();
+    data.setWriteProperties(properties);
+    listData.addEntity(data);
+    EntityCollectionSerializerProperties inlineProperties =
+        EntityCollectionSerializerProperties.serviceRoot(BASE_URI).build();
+
+    listData.setCollectionProperties(inlineProperties);
+    AtomSerializerDeserializer provider = createAtomEntityProvider();
+    roomData.addNavigation("nr_Employees", listData);
+    roomData.setWriteProperties(properties);
+    ODataResponse response =
+        provider.writeEntry(MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms"), roomData);
+
+    String xmlString = verifyResponse(response);
+    assertXpathNotExists("/a:entry/m:properties", xmlString);
+    assertXpathExists("/a:entry/a:link", xmlString);
+    verifyEmployees(employeeXPathString, xmlString);
+  }
+
+  public void entityWithPartialNullInlineFeed() throws Exception {
+    expectedEx.expect(EntityProviderException.class);
+    expectedEx.expectMessage("Entity or expanded entity cannot have null value.");
+    Entity roomData = new Entity();
+    roomData.addProperty("Id", "1");
+    roomData.addProperty("Name", "Neu Schwanstein");
+    roomData.addProperty("Seats", new Integer(20));
+    EntityCollection listData = new EntityCollection();
+    EntitySerializerProperties properties =
+        EntitySerializerProperties.serviceRoot(BASE_URI).build();
+    Entity data = new Entity();
+    data.addProperty("EmployeeId", "1");
+    data.addProperty("EmployeeName", "EmpName1");
+    data.addProperty("RoomId", "1");
+    listData.addEntity(data);
+    data.setWriteProperties(properties);
+
+    data = new Entity();
+    data.addProperty("EmployeeId", "1");
+    data.addProperty("RoomId", "1");
+    data.setWriteProperties(properties);
+    listData.addEntity(data);
+
+    listData.addEntity(null);
+    EntityCollectionSerializerProperties inlineProperties =
+        EntityCollectionSerializerProperties.serviceRoot(BASE_URI).build();
+
+    listData.setCollectionProperties(inlineProperties);
+    AtomSerializerDeserializer provider = createAtomEntityProvider();
+    roomData.addNavigation("nr_Employees", listData);
+    roomData.setWriteProperties(properties);
+    ODataResponse response =
+        provider.writeEntry(MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms"), roomData);
+
+    String xmlString = verifyResponse(response);
+    assertXpathNotExists("/a:entry/m:properties", xmlString);
+    assertXpathExists("/a:entry/a:link", xmlString);
+    verifyEmployees(employeeXPathString, xmlString);
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void entityWithoutIdInlineFeed() throws Exception {
+    Entity roomData = new Entity();
+    roomData.addProperty("Id", "1");
+    roomData.addProperty("Name", "Neu Schwanstein");
+    roomData.addProperty("Seats", new Integer(20));
+    EntityCollection listData = new EntityCollection();
+    EntitySerializerProperties properties =
+        EntitySerializerProperties.serviceRoot(BASE_URI)
+            .includeMetadata(true).build();
+    Entity data = new Entity();
+    data.addProperty("EmployeeName", "EmpName1");
+    data.addProperty("RoomId", "1");
+    listData.addEntity(data);
+    data.setWriteProperties(properties);
+    listData.addEntity(data);
+    EntityCollectionSerializerProperties inlineProperties =
+        EntityCollectionSerializerProperties.serviceRoot(BASE_URI)
+            .build();
+    listData.setCollectionProperties(inlineProperties);
+    AtomSerializerDeserializer provider = createAtomEntityProvider();
+    roomData.addNavigation("nr_Employees", listData);
+    roomData.setWriteProperties(properties);
+    ODataResponse response =
+        provider.writeEntry(MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms"), roomData);
+
+    String xmlString = verifyResponse(response);
+    assertXpathNotExists("/a:entry/m:properties", xmlString);
+    assertXpathExists("/a:entry/a:link", xmlString);
+    verifyEmployees(employeeXPathString, xmlString);
+  }
+
+  @Test
+  public void entityWithEmptyFeed() throws Exception {
+    Entity roomData = new Entity();
+    roomData.addProperty("Id", "1");
+    roomData.addProperty("Name", "Neu Schwanstein");
+    roomData.addProperty("Seats", new Integer(20));
+    EntityCollection listData = new EntityCollection();
+    EntitySerializerProperties properties =
+        EntitySerializerProperties.serviceRoot(BASE_URI)
+            .includeMetadata(true).build();
+
+    AtomSerializerDeserializer provider = createAtomEntityProvider();
+    roomData.addNavigation("nr_Employees", listData);
+    roomData.setWriteProperties(properties);
+    ODataResponse response =
+        provider.writeEntry(MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms"), roomData);
+
+    String xmlString = verifyResponse(response);
+    assertXpathNotExists("/a:entry/m:properties", xmlString);
+    assertXpathExists("/a:entry/a:link", xmlString);
+  }
+
+  @Test
+  public void entityWithEmptyEntityInFeed() throws Exception {
+    Entity roomData = new Entity();
+    roomData.addProperty("Id", "1");
+    roomData.addProperty("Name", "Neu Schwanstein");
+    roomData.addProperty("Seats", new Integer(20));
+    EntityCollection listData = new EntityCollection();
+    EntitySerializerProperties properties =
+        EntitySerializerProperties.serviceRoot(BASE_URI).includeMetadata(false).build();
+    Entity data = new Entity();
+    data.setWriteProperties(properties);
+    listData.addEntity(data);
+    EntityCollectionSerializerProperties inlineProperties =
+        EntityCollectionSerializerProperties.serviceRoot(BASE_URI).build();
+    listData.setCollectionProperties(inlineProperties);
+    AtomSerializerDeserializer provider = createAtomEntityProvider();
+    roomData.addNavigation("nr_Employees", listData);
+    roomData.setWriteProperties(properties);
+    ODataResponse response =
+        provider.writeEntry(MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms"), roomData);
+
+    String xmlString = verifyResponse(response);
+    assertXpathNotExists("/a:entry/m:properties", xmlString);
+    assertXpathExists("/a:entry/a:link", xmlString);
+    assertXpathExists(employeeXPathString, xmlString);
+    assertXpathExists(employeeXPathString + "/m:inline", xmlString);
+
+    assertXpathExists(employeeXPathString + "/m:inline/a:feed[@xml:base='" + BASE_URI + "']", xmlString);
+    assertXpathExists(employeeXPathString + "/m:inline/a:feed/a:entry", xmlString);
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void entityWithNullFeed() throws Exception {
+    Entity roomData = new Entity();
+    roomData.addProperty("Id", "1");
+    roomData.addProperty("Name", "Neu Schwanstein");
+    roomData.addProperty("Seats", new Integer(20));
+
+    EntitySerializerProperties properties =
+        EntitySerializerProperties.serviceRoot(BASE_URI).build();
+
+    AtomSerializerDeserializer provider = createAtomEntityProvider();
+    roomData.addNavigation("nr_Employees", null);
+    roomData.setWriteProperties(properties);
+    ODataResponse response =
+        provider.writeEntry(MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms"), roomData);
+
+    String xmlString = verifyResponse(response);
+    assertXpathNotExists("/a:entry/m:properties", xmlString);
+    assertXpathExists("/a:entry/a:link", xmlString);
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void entityWithNullEntityInFeed() throws Exception {
+    Entity roomData = new Entity();
+    roomData.addProperty("Id", "1");
+    roomData.addProperty("Name", "Neu Schwanstein");
+    roomData.addProperty("Seats", new Integer(20));
+
+    EntitySerializerProperties properties =
+        EntitySerializerProperties.serviceRoot(BASE_URI).build();
+    EntityCollection listData = new EntityCollection();
+    listData.addEntity(null);
+    AtomSerializerDeserializer provider = createAtomEntityProvider();
+    roomData.addNavigation("nr_Employees", listData);
+    roomData.setWriteProperties(properties);
+    ODataResponse response =
+        provider.writeEntry(MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms"), roomData);
+
+    String xmlString = verifyResponse(response);
+    assertXpathNotExists("/a:entry/m:properties", xmlString);
+    assertXpathExists("/a:entry/a:link", xmlString);
+  }
+
+  @Test
+  public void entityWithoutInlineEntityProperty() throws Exception {
+    Entity roomData = new Entity();
+    roomData.addProperty("Id", "1");
+    roomData.addProperty("Name", "Neu Schwanstein");
+    roomData.addProperty("Seats", new Integer(20));
+    EntityCollection listData = new EntityCollection();
+    EntitySerializerProperties properties =
+        EntitySerializerProperties.serviceRoot(BASE_URI)
+            .includeMetadata(true).build();
+    Entity data = new Entity();
+    data.addProperty("EmployeeId", "1");
+    data.addProperty("EmployeeName", "EmpName1");
+    data.addProperty("RoomId", "1");
+    listData.addEntity(data);
+
+    data = new Entity();
+    data.addProperty("EmployeeId", "1");
+    data.addProperty("RoomId", "1");
+    listData.addEntity(data);
+    listData.setGlobalEntityProperties(properties);
+    EntityCollectionSerializerProperties inlineProperties =
+        EntityCollectionSerializerProperties.serviceRoot(BASE_URI).build();
+    listData.setCollectionProperties(inlineProperties);
+    AtomSerializerDeserializer provider = createAtomEntityProvider();
+    roomData.addNavigation("nr_Employees", listData);
+    roomData.setWriteProperties(properties);
+    ODataResponse response =
+        provider.writeEntry(MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms"), roomData);
+
+    String xmlString = verifyResponse(response);
+    assertXpathNotExists("/a:entry/m:properties", xmlString);
+    assertXpathExists("/a:entry/a:link", xmlString);
+    verifyEmployees(employeeXPathString, xmlString);
+  }
+
+  @Test
+  public void entityWithoutInlineCollectionProperty() throws Exception {
+    Entity roomData = new Entity();
+    roomData.addProperty("Id", "1");
+    roomData.addProperty("Name", "Neu Schwanstein");
+    roomData.addProperty("Seats", new Integer(20));
+    EntityCollection listData = new EntityCollection();
+    EntitySerializerProperties properties =
+        EntitySerializerProperties.serviceRoot(BASE_URI)
+            .includeMetadata(true).build();
+    Entity data = new Entity();
+    data.addProperty("EmployeeId", "1");
+    data.addProperty("EmployeeName", "EmpName1");
+    data.addProperty("RoomId", "1");
+    data.setWriteProperties(properties);
+    listData.addEntity(data);
+
+    data = new Entity();
+    data.addProperty("EmployeeId", "1");
+    data.addProperty("RoomId", "1");
+    data.setWriteProperties(properties);
+    listData.addEntity(data);
+    AtomSerializerDeserializer provider = createAtomEntityProvider();
+    roomData.addNavigation("nr_Employees", listData);
+    roomData.setWriteProperties(properties);
+    ODataResponse response =
+        provider.writeEntry(MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms"), roomData);
+
+    String xmlString = verifyResponse(response);
+    assertXpathNotExists("/a:entry/m:properties", xmlString);
+    assertXpathExists("/a:entry/a:link", xmlString);
+    verifyEmployees(employeeXPathString, xmlString);
+  }
+
+  @Test
+  public void entityWithoutPropertyInlineFeed() throws Exception {
+    Entity roomData = new Entity();
+    roomData.addProperty("Id", "1");
+    roomData.addProperty("Name", "Neu Schwanstein");
+    roomData.addProperty("Seats", new Integer(20));
+    EntityCollection listData = new EntityCollection();
+    EntitySerializerProperties properties =
+        EntitySerializerProperties.serviceRoot(BASE_URI)
+            .includeMetadata(false).build();
+    Entity data = new Entity();
+    data.addProperty("EmployeeId", "1");
+    data.addProperty("EmployeeName", "EmpName1");
+    data.addProperty("RoomId", "1");
+    listData.addEntity(data);
+
+    data = new Entity();
+    data.addProperty("EmployeeId", "1");
+    data.addProperty("RoomId", "1");
+    listData.setGlobalEntityProperties(properties);
+    listData.addEntity(data);
+    AtomSerializerDeserializer provider = createAtomEntityProvider();
+    roomData.addNavigation("nr_Employees", listData);
+    roomData.setWriteProperties(properties);
+    ODataResponse response =
+        provider.writeEntry(MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms"), roomData);
+
+    String xmlString = verifyResponse(response);
+    assertXpathNotExists("/a:entry/m:properties", xmlString);
+    assertXpathExists("/a:entry/a:link", xmlString);
+    verifyEmployeesContent(employeeXPathString, xmlString);
+  }
+
+  @Test
+  public void entityWithPropertyAtCollectionForInlineFeed() throws Exception {
+    Entity roomData = new Entity();
+    roomData.addProperty("Id", "1");
+    roomData.addProperty("Name", "Neu Schwanstein");
+    roomData.addProperty("Seats", new Integer(20));
+    EntityCollection listData = new EntityCollection();
+    EntitySerializerProperties properties =
+        EntitySerializerProperties.serviceRoot(BASE_URI)
+            .includeMetadata(false).build();
+    Entity data = new Entity();
+    data.addProperty("EmployeeId", "1");
+    data.addProperty("EmployeeName", "EmpName1");
+    data.addProperty("RoomId", "1");
+    listData.addEntity(data);
+
+    data = new Entity();
+    data.addProperty("EmployeeId", "1");
+    data.addProperty("RoomId", "1");
+    listData.addEntity(data);
+    AtomSerializerDeserializer provider = createAtomEntityProvider();
+    roomData.addNavigation("nr_Employees", listData);
+    roomData.setWriteProperties(properties);
+    ODataResponse response =
+        provider.writeEntry(MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms"), roomData);
+
+    String xmlString = verifyResponse(response);
+    assertXpathNotExists("/a:entry/m:properties", xmlString);
+    assertXpathExists("/a:entry/a:link", xmlString);
+
+    verifyEmployeesContent(employeeXPathString, xmlString);
+  }
+
+  @Test
+  public void entityWithTwoPropertyInlineFeed() throws Exception {
+    Entity roomData = new Entity();
+    roomData.addProperty("Id", "1");
+    roomData.addProperty("Name", "Neu Schwanstein");
+    roomData.addProperty("Seats", new Integer(20));
+    EntityCollection listData = new EntityCollection();
+    EntitySerializerProperties properties =
+        EntitySerializerProperties.serviceRoot(BASE_URI)
+            .includeMetadata(true).build();
+    URI COLL_URI = new URI("http://host:80/service/collection/");
+    EntityCollectionSerializerProperties collProperties =
+        EntityCollectionSerializerProperties.serviceRoot(COLL_URI).build();
+    listData.setCollectionProperties(collProperties);
+    listData.setGlobalEntityProperties(properties);
+    Entity data = new Entity();
+    data.addProperty("EmployeeId", "1");
+    data.addProperty("EmployeeName", "EmpName1");
+    data.addProperty("RoomId", "1");
+    listData.addEntity(data);
+
+    data = new Entity();
+    data.addProperty("EmployeeId", "1");
+    data.addProperty("RoomId", "1");
+
+    listData.addEntity(data);
+    AtomSerializerDeserializer provider = createAtomEntityProvider();
+    roomData.addNavigation("nr_Employees", listData);
+    roomData.setWriteProperties(properties);
+    ODataResponse response =
+        provider.writeEntry(MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms"), roomData);
+
+    String xmlString = verifyResponse(response);
+    assertXpathNotExists("/a:entry/m:properties", xmlString);
+    assertXpathExists("/a:entry/a:link", xmlString);
+    verifyEmployeesForCollection(employeeXPathString, xmlString, COLL_URI);
+  }
+
+  private void verifyEmployees(final String path, final String xmlString) throws XpathException, IOException,
+      SAXException {
+    assertXpathExists(path, xmlString);
+    assertXpathExists(path + "/m:inline", xmlString);
+
+    assertXpathExists(path + "/m:inline/a:feed[@xml:base='" + BASE_URI + "']", xmlString);
+    assertXpathExists(path + "/m:inline/a:feed/a:entry", xmlString);
+    assertXpathExists(path + "/m:inline/a:feed/a:entry/a:id", xmlString);
+    assertXpathExists(path + "/m:inline/a:feed/a:entry/a:title", xmlString);
+    assertXpathExists(path + "/m:inline/a:feed/a:entry/a:updated", xmlString);
+
+    assertXpathExists(path + "/m:inline/a:feed/a:entry/a:category", xmlString);
+    assertXpathExists(path + "/m:inline/a:feed/a:entry/a:link", xmlString);
+
+    assertXpathExists(path + "/m:inline/a:feed/a:entry/a:content", xmlString);
+    assertXpathExists(path + "/m:inline/a:feed/a:entry/m:properties", xmlString);
+    assertXpathExists(path + "/m:inline/a:feed/a:entry/m:properties/d:EmployeeId", xmlString);
+    assertXpathExists(path + "/m:inline/a:feed/a:entry/m:properties/d:EmployeeName", xmlString);
+    assertXpathExists(path + "/m:inline/a:feed/a:entry/m:properties/d:RoomId", xmlString);
+
+    assertXpathExists("/a:entry/a:content/m:properties/d:Id", xmlString);
+    assertXpathExists("/a:entry/a:content/m:properties/d:Name", xmlString);
+    assertXpathExists("/a:entry/a:content/m:properties/d:Seats", xmlString);
+
+  }
+
+  private void verifyEmployeesContent(final String path, final String xmlString) throws XpathException, IOException,
+      SAXException {
+    assertXpathExists(path, xmlString);
+    assertXpathExists(path + "/m:inline", xmlString);
+
+    assertXpathExists(path + "/m:inline/a:feed[@xml:base='" + BASE_URI + "']", xmlString);
+    assertXpathExists(path + "/m:inline/a:feed/a:entry", xmlString);
+    assertXpathExists(path + "/m:inline/a:feed/a:entry/m:properties", xmlString);
+    assertXpathExists(path + "/m:inline/a:feed/a:entry/m:properties/d:EmployeeId", xmlString);
+    assertXpathExists(path + "/m:inline/a:feed/a:entry/m:properties/d:EmployeeName", xmlString);
+    assertXpathExists(path + "/m:inline/a:feed/a:entry/m:properties/d:RoomId", xmlString);
+
+    assertXpathExists("/a:entry/a:content/m:properties/d:Id", xmlString);
+    assertXpathExists("/a:entry/a:content/m:properties/d:Name", xmlString);
+    assertXpathExists("/a:entry/a:content/m:properties/d:Seats", xmlString);
+
+  }
+
+  private void verifyEmployeesForCollection(final String path, final String xmlString, URI coll_uri)
+      throws XpathException, IOException,
+      SAXException {
+    assertXpathExists(path, xmlString);
+    assertXpathExists(path + "/m:inline", xmlString);
+
+    assertXpathExists(path + "/m:inline/a:feed[@xml:base='" + coll_uri + "']", xmlString);
+    assertXpathExists(path + "/m:inline/a:feed/a:entry", xmlString);
+    assertXpathExists(path + "/m:inline/a:feed/a:entry/a:id", xmlString);
+    assertXpathExists(path + "/m:inline/a:feed/a:entry/a:title", xmlString);
+    assertXpathExists(path + "/m:inline/a:feed/a:entry/a:updated", xmlString);
+
+    assertXpathExists(path + "/m:inline/a:feed/a:entry/a:category", xmlString);
+    assertXpathExists(path + "/m:inline/a:feed/a:entry/a:link", xmlString);
+
+    assertXpathExists(path + "/m:inline/a:feed/a:entry/a:content", xmlString);
+    assertXpathExists(path + "/m:inline/a:feed/a:entry/m:properties", xmlString);
+    assertXpathExists(path + "/m:inline/a:feed/a:entry/m:properties/d:EmployeeId", xmlString);
+    assertXpathExists(path + "/m:inline/a:feed/a:entry/m:properties/d:EmployeeName", xmlString);
+    assertXpathExists(path + "/m:inline/a:feed/a:entry/m:properties/d:RoomId", xmlString);
+
+    assertXpathExists("/a:entry/a:content/m:properties/d:Id", xmlString);
+    assertXpathExists("/a:entry/a:content/m:properties/d:Name", xmlString);
+    assertXpathExists("/a:entry/a:content/m:properties/d:Seats", xmlString);
+
+  }
+
+  private String verifyResponse(final ODataResponse response) throws IOException {
+    assertNotNull(response);
+    assertNotNull(response.getEntity());
+    assertNull("EntityProvider should not set content header", response.getContentHeader());
+    String xmlString = StringHelper.inputStreamToString((InputStream) response.getEntity());
+    return xmlString;
+  }
+
+  @Test
+  public void feed() throws Exception {
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+    EntityCollection teamsData = new EntityCollection();
+    Entity team1Data = new Entity();
+    team1Data.addProperty("Id", "1");
+    team1Data.addProperty("isScrumTeam", true);
+    Entity team2Data = new Entity();
+    team2Data.addProperty("Id", "2");
+    team2Data.addProperty("isScrumTeam", false);
+    teamsData.addEntity(team1Data);
+    teamsData.addEntity(team2Data);
+    teamsData.setCollectionProperties(EntityCollectionSerializerProperties.serviceRoot(BASE_URI).build());
+
+    final ODataResponse response = new AtomSerializerDeserializer().writeFeed(entitySet, teamsData);
+    assertNotNull(response);
+    assertNotNull(response.getEntity());
+    assertNull("EntitypProvider must not set content header", response.getContentHeader());
+
+    final String xmlString = verifyResponse(response);
+    assertNotNull(xmlString);
+    assertXpathExists("/a:feed", xmlString);
+    assertXpathExists("/a:feed/a:entry/a:content/m:properties", xmlString);
+    assertXpathExists("/a:feed/a:entry/a:content/m:properties/d:Id", xmlString);
+    assertXpathExists("/a:feed/a:entry/a:content/m:properties/d:isScrumTeam", xmlString);    
+  }
+  
+  @Test
+  public void feedWithEmptyData() throws Exception {
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+    EntityCollection teamsData = new EntityCollection();
+    Entity team1Data = new Entity();
+    team1Data.addProperty("Id", "1");
+    team1Data.addProperty("isScrumTeam", true);
+    Entity team2Data = new Entity();
+    teamsData.addEntity(team1Data);
+    teamsData.addEntity(team2Data);
+    teamsData.setCollectionProperties(EntityCollectionSerializerProperties.serviceRoot(BASE_URI).build());
+
+    final ODataResponse response = new AtomSerializerDeserializer().writeFeed(entitySet, teamsData);
+    assertNotNull(response);
+    assertNotNull(response.getEntity());
+    assertNull("EntitypProvider must not set content header", response.getContentHeader());
+
+    final String xmlString = verifyResponse(response);
+    assertNotNull(xmlString);
+    assertTrue(xmlString.contains("<entry><content type=\"application/xml\">"
+        + "<m:properties><d:Id>1</d:Id><d:isScrumTeam>true</d:isScrumTeam></m:properties>"
+        + "</content></entry>"));
+    assertTrue(xmlString.contains("<entry><content type=\"application/xml\"/></entry>"));
+  }
+  
+  @Test
+  public void feedWithNullData() throws Exception {
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+    
+    try {
+      new AtomSerializerDeserializer().writeFeed(entitySet, null);
+    } catch (EntityProviderException e) {
+      assertEquals(ERROR_MSG, e.getMessage());
+    }
+  }
+  
+  @Test
+  public void feedWithMetadata() throws Exception {
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+    EntityCollection teamsData = new EntityCollection();
+    Entity team1Data = new Entity();
+    team1Data.addProperty("Id", "1");
+    team1Data.addProperty("isScrumTeam", true);
+    team1Data.setWriteProperties(EntitySerializerProperties.serviceRoot(BASE_URI).includeMetadata(true).build());
+    Entity team2Data = new Entity();
+    team2Data.addProperty("Id", "2");
+    team2Data.addProperty("isScrumTeam", false);
+    team2Data.setWriteProperties(EntitySerializerProperties.serviceRoot(BASE_URI).includeMetadata(true).build());
+    teamsData.addEntity(team1Data);
+    teamsData.addEntity(team2Data);
+    teamsData.setCollectionProperties(EntityCollectionSerializerProperties.serviceRoot(BASE_URI).build());
+
+    final ODataResponse response = new AtomSerializerDeserializer().writeFeed(entitySet, teamsData);
+    assertNotNull(response);
+    assertNotNull(response.getEntity());
+    assertNull("EntitypProvider must not set content header", response.getContentHeader());
+
+    final String xmlString = StringHelper.inputStreamToString((InputStream) response.getEntity());
+    assertNotNull(xmlString);
+    assertXpathExists("/a:feed", xmlString);
+    assertXpathExists("/a:feed/a:entry/a:id", xmlString);
+    assertXpathExists("/a:feed/a:entry/a:content/m:properties", xmlString);
+    assertXpathExists("/a:feed/a:entry/a:content/m:properties/d:Id", xmlString);
+    assertXpathExists("/a:feed/a:entry/a:content/m:properties/d:isScrumTeam", xmlString);
+  }
+  
+  @Test
+  public void feedWithGlobalEntityProperties() throws Exception {
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+    EntityCollection teamsData = new EntityCollection();
+    Entity team1Data = new Entity();
+    team1Data.addProperty("Id", "1");
+    team1Data.addProperty("isScrumTeam", true);
+    Entity team2Data = new Entity();
+    team2Data.addProperty("Id", "2");
+    team2Data.addProperty("isScrumTeam", false);
+    teamsData.addEntity(team1Data);
+    teamsData.addEntity(team2Data);
+    teamsData.setCollectionProperties(EntityCollectionSerializerProperties.serviceRoot(BASE_URI).build());
+    teamsData.setGlobalEntityProperties(EntitySerializerProperties.serviceRoot(BASE_URI).
+        includeMetadata(true).build());
+    
+    final ODataResponse response = new AtomSerializerDeserializer().writeFeed(entitySet, teamsData);
+    final String xmlString = StringHelper.inputStreamToString((InputStream) response.getEntity());
+    assertNotNull(xmlString);
+    assertXpathExists("/a:feed", xmlString);
+    assertXpathExists("/a:feed/a:entry/a:id", xmlString);
+    assertXpathExists("/a:feed/a:entry/a:content/m:properties", xmlString);
+    assertXpathExists("/a:feed/a:entry/a:content/m:properties/d:Id", xmlString);
+    assertXpathExists("/a:feed/a:entry/a:content/m:properties/d:isScrumTeam", xmlString);
+  }
+  
+  @Test
+  public void feedWithoutCollectionProperties() throws Exception {
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+    EntityCollection teamsData = new EntityCollection();
+    Entity team1Data = new Entity();
+    team1Data.addProperty("Id", "1");
+    team1Data.addProperty("isScrumTeam", true);
+    team1Data.setWriteProperties(EntitySerializerProperties.serviceRoot(BASE_URI).
+        includeMetadata(true).build());
+    Entity team2Data = new Entity();
+    team2Data.addProperty("Id", "2");
+    team2Data.addProperty("isScrumTeam", false);
+    team2Data.setWriteProperties(EntitySerializerProperties.serviceRoot(BASE_URI).
+        includeMetadata(true).build());
+    teamsData.addEntity(team1Data);
+    teamsData.addEntity(team2Data);
+    
+    try {
+      new AtomSerializerDeserializer().writeFeed(entitySet, teamsData);
+    } catch (EntityProviderException e) {
+      assertEquals(EXP_MSG, e.getMessage());
+    }
+  }
+  
+  @Test
+  public void unbalancedPropertyFeedWithInlineFeed() throws Exception {
+    Edm edm = MockFacade.getMockEdm();
+    EdmTyped imageUrlProperty = edm.getEntityType("RefScenario", "Employee").getProperty("ImageUrl");
+    EdmFacets facets = mock(EdmFacets.class);
+    when(facets.getMaxLength()).thenReturn(1);
+    when(((EdmProperty) imageUrlProperty).getFacets()).thenReturn(facets);
+
+    EntityCollection roomsData = new EntityCollection();
+    Entity room1Data = new Entity();
+    room1Data.addProperty("Id", "1");
+    room1Data.addProperty("Name", "Neu Schwanstein");
+    room1Data.addProperty("Seats", new Integer(20));
+    room1Data.setWriteProperties(EntitySerializerProperties.serviceRoot(BASE_URI).
+        validatingFacets(true).build());
+    
+    EntityCollection innerData = new EntityCollection();
+    Entity data = new Entity();
+    data.addProperty("EmployeeId", "1");
+    data.addProperty("EmployeeName", "EmpName1");
+    data.addProperty("RoomId", "1");
+    innerData.addEntity(data);
+    
+    data = new Entity();
+    data.addProperty("EmployeeId", "1");
+    data.addProperty("RoomId", "1");
+    innerData.addEntity(data);
+    
+    room1Data.addNavigation("nr_Employees", innerData);
+    roomsData.addEntity(room1Data);
+    
+    Entity room2Data = new Entity();
+    room2Data.addProperty("Id", "2");
+    room2Data.addProperty("Name", "John");
+    room2Data.addProperty("Seats", new Integer(10));
+    room2Data.setWriteProperties(EntitySerializerProperties.serviceRoot(BASE_URI).
+        validatingFacets(true).build());
+    
+    innerData = new EntityCollection();
+    data = new Entity();
+    data.addProperty("EmployeeId", "2");
+    data.addProperty("EmployeeName", "EmpName2");
+    data.addProperty("RoomId", "2");
+    innerData.addEntity(data);
+    
+    data = new Entity();
+    data.addProperty("EmployeeId", "2");
+    data.addProperty("RoomId", "2");
+    innerData.addEntity(data);
+    
+    room2Data.addNavigation("nr_Employees", innerData);
+    roomsData.addEntity(room2Data);
+    
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Rooms");
+    roomsData.setCollectionProperties(EntityCollectionSerializerProperties.serviceRoot(BASE_URI).build());
+    final ODataResponse response =
+        new AtomSerializerDeserializer().writeFeed(entitySet, roomsData);
+    final String xmlString = StringHelper.inputStreamToString((InputStream) response.getEntity());
+    assertNotNull(xmlString);
+    verifyRoomsFeedWithInlineEmployeeFeed(xmlString, BASE_URI);
+  }
+  
+  private void verifyRoomsFeedWithInlineEmployeeFeed(final String xmlString, URI coll_uri)
+      throws XpathException, IOException,
+      SAXException {
+    assertXpathExists("/a:feed[@xml:base='" + coll_uri + "']", xmlString);
+    assertXpathExists("/a:feed/a:entry/a:link/m:inline", xmlString);
+
+    assertXpathExists("/a:feed/a:entry/a:link/m:inline/a:feed[@xml:base='" + coll_uri + "']", xmlString);
+    assertXpathExists("/a:feed/a:entry/a:link/m:inline/a:feed/a:entry", xmlString);
+    assertXpathExists("/a:feed/a:entry/a:link/m:inline/a:feed/a:entry/m:properties/d:EmployeeId", xmlString);
+    assertXpathExists("/a:feed/a:entry/a:link/m:inline/a:feed/a:entry/m:properties/d:RoomId", xmlString);
+
+    assertXpathExists("/a:feed/a:entry/a:content", xmlString);
+    assertXpathExists("/a:feed/a:entry/a:content/m:properties", xmlString);
+    assertXpathExists("/a:feed/a:entry/a:content/m:properties/d:Id", xmlString);
+    assertXpathExists("/a:feed/a:entry/a:content/m:properties/d:Name", xmlString);
+    assertXpathExists("/a:feed/a:entry/a:content/m:properties/d:Seats", xmlString);
+
+  }
+  
+  @Test
+  public void unbalancedPropertyFeedWithInlineFeedAndNavigationLink() throws Exception {
+    Edm edm = MockFacade.getMockEdm();
+    EdmTyped imageUrlProperty = edm.getEntityType("RefScenario", "Employee").getProperty("ImageUrl");
+    EdmFacets facets = mock(EdmFacets.class);
+    when(facets.getMaxLength()).thenReturn(1);
+    when(((EdmProperty) imageUrlProperty).getFacets()).thenReturn(facets);
+
+    EntityCollection roomsData = new EntityCollection();
+    Entity room1Data = new Entity();
+    room1Data.addProperty("Id", "1");
+    room1Data.addProperty("Name", "Neu Schwanstein");
+    room1Data.addProperty("Seats", new Integer(20));
+    room1Data.setWriteProperties(EntitySerializerProperties.serviceRoot(BASE_URI).
+        validatingFacets(true).build());
+    
+    EntityCollection innerData = new EntityCollection();
+    Entity data = new Entity();
+    data.addProperty("EmployeeId", "1");
+    data.addProperty("EmployeeName", "EmpName1");
+    data.addProperty("RoomId", "1");
+    innerData.addEntity(data);
+    
+    data = new Entity();
+    data.addProperty("EmployeeId", "1");
+    data.addProperty("RoomId", "1");
+    innerData.addEntity(data);
+    
+    room1Data.addNavigation("nr_Employees", innerData);
+    Map<String, Object> link1 = new HashMap<String, Object>();
+    link1.put("Id", 1);
+    room1Data.addNavigation("nr_Building", link1);
+    roomsData.addEntity(room1Data);
+    
+    Entity room2Data = new Entity();
+    room2Data.addProperty("Id", "2");
+    room2Data.addProperty("Name", "John");
+    room2Data.addProperty("Seats", new Integer(10));
+    room2Data.setWriteProperties(EntitySerializerProperties.serviceRoot(BASE_URI).
+        validatingFacets(true).build());
+    
+    innerData = new EntityCollection();
+    data = new Entity();
+    data.addProperty("EmployeeId", "2");
+    data.addProperty("EmployeeName", "EmpName2");
+    data.addProperty("RoomId", "2");
+    innerData.addEntity(data);
+    
+    data = new Entity();
+    data.addProperty("EmployeeId", "2");
+    data.addProperty("RoomId", "2");
+    innerData.addEntity(data);
+    
+    room2Data.addNavigation("nr_Employees", innerData);
+    Map<String, Object> link2 = new HashMap<String, Object>();
+    link2.put("Id", 2);
+    room2Data.addNavigation("nr_Building", link2);
+    roomsData.addEntity(room2Data);
+    roomsData.setCollectionProperties(EntityCollectionSerializerProperties.serviceRoot(BASE_URI).build());
+    
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Rooms");
+    final ODataResponse response =
+        new AtomSerializerDeserializer().writeFeed(entitySet, roomsData);
+    
+    final String xmlString = StringHelper.inputStreamToString((InputStream) response.getEntity());
+    assertNotNull(xmlString);
+    verifyRoomsFeedWithInlineEmployeeFeedWithNavigationLinks(xmlString, BASE_URI);
+  }
+
+  @Test
+  public void unbalancedPropertyFeedWithInlineFeedAndNavigationLinkWithoutKey() throws Exception {
+    Edm edm = MockFacade.getMockEdm();
+    EdmTyped imageUrlProperty = edm.getEntityType("RefScenario", "Employee").getProperty("ImageUrl");
+    EdmFacets facets = mock(EdmFacets.class);
+    when(facets.getMaxLength()).thenReturn(1);
+    when(((EdmProperty) imageUrlProperty).getFacets()).thenReturn(facets);
+
+    EntityCollection roomsData = new EntityCollection();
+    Entity room1Data = new Entity();
+    room1Data.addProperty("Name", "Neu Schwanstein");
+    room1Data.addProperty("Seats", new Integer(20));
+    room1Data.setWriteProperties(EntitySerializerProperties.serviceRoot(BASE_URI).
+        validatingFacets(false).isKeyAutoGenerated(true).build());
+    
+    EntityCollection innerData = new EntityCollection();
+    Entity data = new Entity();
+    data.addProperty("EmployeeName", "EmpName1");
+    data.addProperty("RoomId", "1");
+    innerData.addEntity(data);
+    
+    data = new Entity();
+    data.addProperty("RoomId", "1");
+    innerData.addEntity(data);
+    
+    room1Data.addNavigation("nr_Employees", innerData);
+    Map<String, Object> link1 = new HashMap<String, Object>();
+    link1.put("Id", 1);
+    room1Data.addNavigation("nr_Building", link1);
+    roomsData.addEntity(room1Data);
+    
+    Entity room2Data = new Entity();
+    room2Data.addProperty("Name", "John");
+    room2Data.addProperty("Seats", new Integer(10));
+    room2Data.setWriteProperties(EntitySerializerProperties.serviceRoot(BASE_URI).
+        validatingFacets(false).isKeyAutoGenerated(true).build());
+    
+    innerData = new EntityCollection();
+    data = new Entity();
+    data.addProperty("EmployeeName", "EmpName2");
+    data.addProperty("RoomId", "2");
+    innerData.addEntity(data);
+    
+    data = new Entity();
+    data.addProperty("RoomId", "2");
+    innerData.addEntity(data);
+    
+    room2Data.addNavigation("nr_Employees", innerData);
+    Map<String, Object> link2 = new HashMap<String, Object>();
+    link2.put("Id", 2);
+    room2Data.addNavigation("nr_Building", link2);
+    roomsData.addEntity(room2Data);
+    roomsData.setCollectionProperties(EntityCollectionSerializerProperties.serviceRoot(BASE_URI).build());
+    
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Rooms");
+    final ODataResponse response =
+        new AtomSerializerDeserializer().writeFeed(entitySet, roomsData);
+    
+    final String xmlString = StringHelper.inputStreamToString((InputStream) response.getEntity());
+    assertNotNull(xmlString);
+    verifyRoomsFeedWithInlineEmployeeFeedWithNavigationLinksWithoutKeys(xmlString, BASE_URI);
+  }
+  
+  private void verifyRoomsFeedWithInlineEmployeeFeedWithNavigationLinks(String xmlString, URI coll_uri) 
+      throws XpathException, IOException, SAXException {
+    assertXpathExists("/a:feed[@xml:base='" + coll_uri + "']", xmlString);
+    assertXpathExists("/a:feed/a:entry/a:link/m:inline", xmlString);
+    assertXpathExists("/a:feed/a:entry/a:link[@href=\"Buildings('1')\"]", xmlString);
+
+    assertXpathExists("/a:feed/a:entry/a:link/m:inline/a:feed[@xml:base='" + coll_uri + "']", xmlString);
+    assertXpathExists("/a:feed/a:entry/a:link/m:inline/a:feed/a:entry", xmlString);
+    assertXpathExists("/a:feed/a:entry/a:link/m:inline/a:feed/a:entry/m:properties/d:EmployeeId", xmlString);
+    assertXpathExists("/a:feed/a:entry/a:link/m:inline/a:feed/a:entry/m:properties/d:RoomId", xmlString);
+
+    assertXpathExists("/a:feed/a:entry/a:content", xmlString);
+    assertXpathExists("/a:feed/a:entry/a:content/m:properties", xmlString);
+    assertXpathExists("/a:feed/a:entry/a:content/m:properties/d:Id", xmlString);
+    assertXpathExists("/a:feed/a:entry/a:content/m:properties/d:Name", xmlString);
+    assertXpathExists("/a:feed/a:entry/a:content/m:properties/d:Seats", xmlString);
+    
+  }
+  
+  @Test
+  public void unbalancedPropertyFeedWithInlineEntryAndNavigationLink() throws Exception {
+    Edm edm = MockFacade.getMockEdm();
+    EdmTyped imageUrlProperty = edm.getEntityType("RefScenario", "Employee").getProperty("ImageUrl");
+    EdmFacets facets = mock(EdmFacets.class);
+    when(facets.getMaxLength()).thenReturn(1);
+    when(((EdmProperty) imageUrlProperty).getFacets()).thenReturn(facets);
+
+    EntityCollection roomsData = new EntityCollection();
+    Entity room1Data = new Entity();
+    room1Data.addProperty("Id", "1");
+    room1Data.addProperty("Name", "Neu Schwanstein");
+    room1Data.addProperty("Seats", new Integer(20));
+    room1Data.setWriteProperties(EntitySerializerProperties.serviceRoot(BASE_URI).
+        validatingFacets(true).build());
+    
+    Map<String, Object> link1 = new HashMap<String, Object>();
+    link1.put("Id", 1);
+    room1Data.addNavigation("nr_Building", link1);
+    roomsData.addEntity(room1Data);
+    
+    Entity room2Data = new Entity();
+    room2Data.addProperty("Id", "2");
+    room2Data.addProperty("Name", "John");
+    room2Data.addProperty("Seats", new Integer(10));
+    room2Data.setWriteProperties(EntitySerializerProperties.serviceRoot(BASE_URI).
+        validatingFacets(true).build());
+    
+    Entity data = new Entity();
+    data.addProperty("Id", "2");
+    data.addProperty("Name", "Team2");
+    
+    room2Data.addNavigation("nr_Building", data);
+    roomsData.addEntity(room2Data);
+    roomsData.setCollectionProperties(EntityCollectionSerializerProperties.serviceRoot(BASE_URI).build());
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Rooms");
+    final ODataResponse response =
+        new AtomSerializerDeserializer().writeFeed(entitySet, roomsData);
+    assertNotNull(response);
+    assertNotNull(response.getEntity());
+
+    final String xmlString = StringHelper.inputStreamToString((InputStream) response.getEntity());
+    assertNotNull(xmlString);
+    assertXpathExists("/a:feed[@xml:base=\"http://host:80/service/\"]", xmlString);
+    assertXpathExists("/a:feed/a:entry/a:link/m:inline", xmlString);
+    assertXpathExists("/a:feed/a:entry/a:link/m:inline/a:entry/a:content/m:properties", xmlString);
+    assertXpathExists("/a:feed/a:entry/a:link/m:inline/a:entry/a:content/m:properties/d:Id", xmlString);
+    assertXpathExists("/a:feed/a:entry/a:link/m:inline/a:entry/a:content/m:properties/d:Name", xmlString);
+    assertXpathExists("/a:feed/a:entry/a:link[@href=\"Buildings('1')\"]", xmlString);
+  }
+  
+  private void verifyRoomsFeedWithInlineEmployeeFeedWithNavigationLinksWithoutKeys(String xmlString, URI coll_uri) 
+      throws XpathException, IOException, SAXException {
+    assertXpathExists("/a:feed[@xml:base='" + coll_uri + "']", xmlString);
+    assertXpathExists("/a:feed/a:entry/a:link[@href=\"Rooms('A')/nr_Employees\"]", xmlString);
+    assertXpathExists("/a:feed/a:entry/a:link/m:inline", xmlString);
+    assertXpathExists("/a:feed/a:entry/a:link[@href=\"Buildings('1')\"]", xmlString);
+
+    assertXpathExists("/a:feed/a:entry/a:link/m:inline/a:feed[@xml:base='" + coll_uri + "']", xmlString);
+    assertXpathExists("/a:feed/a:entry/a:link/m:inline/a:feed/a:entry", xmlString);
+    assertXpathNotExists("/a:feed/a:entry/a:link/m:inline/a:feed/a:entry/m:properties/d:EmployeeId", xmlString);
+    assertXpathExists("/a:feed/a:entry/a:link/m:inline/a:feed/a:entry/m:properties/d:RoomId", xmlString);
+
+    assertXpathExists("/a:feed/a:entry/a:content", xmlString);
+    assertXpathExists("/a:feed/a:entry/a:content/m:properties", xmlString);
+    assertXpathExists("/a:feed/a:entry/a:content/m:properties/d:Name", xmlString);
+    assertXpathExists("/a:feed/a:entry/a:content/m:properties/d:Seats", xmlString);
+    
+  }
+}


[18/24] olingo-odata2 git commit: [OLINGO-1253]Client Module for Olingo v2

Posted by ar...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/XmlPropertyDeserializer.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/XmlPropertyDeserializer.java b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/XmlPropertyDeserializer.java
new file mode 100644
index 0000000..53370bc
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/XmlPropertyDeserializer.java
@@ -0,0 +1,199 @@
+/*******************************************************************************
+ * 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.client.core.ep.deserializer;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmLiteralKind;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.edm.EdmSimpleType;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeException;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.client.api.ep.DeserializerProperties;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityComplexPropertyInfo;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityInfoAggregator;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityPropertyInfo;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityTypeMapping;
+import org.apache.olingo.odata2.core.ep.util.FormatXml;
+
+/**
+ * XML property consumer.
+ */
+public class XmlPropertyDeserializer {
+
+  protected static final String TRUE = "true";
+  protected static final String FALSE = "false";
+
+  /**
+   * Read property of every entry in a payload
+   * @param reader
+   * @param property
+   * @param readProperties
+   * @return Map<String, Object>
+   * @throws EntityProviderException
+   */
+  public Map<String, Object> readProperty(final XMLStreamReader reader, final EdmProperty property,
+      final DeserializerProperties readProperties) throws EntityProviderException {
+    return readProperty(reader, EntityInfoAggregator.create(property), readProperties);
+  }
+
+  /**
+   * Read property of every entry in a payload
+   * @param reader
+   * @param propertyInfo
+   * @param readProperties
+   * @return Map<String, Object>
+   * @throws EntityProviderException
+   */
+  public Map<String, Object> readProperty(final XMLStreamReader reader, final EntityPropertyInfo propertyInfo,
+      final DeserializerProperties readProperties) throws EntityProviderException {
+    final EntityTypeMapping typeMappings =
+        EntityTypeMapping.create(readProperties  == null ? Collections.<String, Object> emptyMap() :
+      readProperties.getTypeMappings());
+    try {
+      reader.next();
+
+      Object value = readStartedElement(reader, propertyInfo.getName(), propertyInfo, typeMappings, readProperties);
+
+      Map<String, Object> result = new HashMap<String, Object>();
+      result.put(propertyInfo.getName(), value);
+      return result;
+    } catch (XMLStreamException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass()
+          .getSimpleName()), e);
+    } catch (EdmException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass()
+          .getSimpleName()), e);
+    }
+  }
+
+
+  /**
+   * Deserializes a collection of entities
+   * @param reader
+   * @param info
+   * @param properties
+   * @return List<Object>
+   * @throws EntityProviderException
+   */
+  public List<Object> readCollection(XMLStreamReader reader, final EntityPropertyInfo info,
+      final DeserializerProperties properties) throws EntityProviderException {
+    final String collectionName = info.getName();
+    final EntityTypeMapping typeMappings = EntityTypeMapping.create(
+        properties == null || !properties.getTypeMappings().containsKey(collectionName) ?
+            Collections.<String, Object> emptyMap() :
+            Collections.<String, Object> singletonMap(FormatXml.D_ELEMENT,
+                properties.getTypeMappings().get(collectionName)));
+    List<Object> result = new ArrayList<Object>();
+    try {
+      reader.nextTag();
+      reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_D_2007_08, collectionName);
+      reader.nextTag();
+      while (reader.isStartElement()) {
+        result.add(readStartedElement(reader, FormatXml.D_ELEMENT, info, typeMappings, properties));
+        reader.nextTag();
+      }
+      reader.require(XMLStreamConstants.END_ELEMENT, Edm.NAMESPACE_D_2007_08, collectionName);
+      reader.next();
+      reader.require(XMLStreamConstants.END_DOCUMENT, null, null);
+      return result;
+    } catch (final XMLStreamException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED
+          .addContent(e.getClass().getSimpleName()), e);
+    } catch (final EdmException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED
+          .addContent(e.getClass().getSimpleName()), e);
+    }
+  }
+
+  protected Object readStartedElement(XMLStreamReader reader, final String name, //NOSONAR
+      final EntityPropertyInfo propertyInfo, 
+      final EntityTypeMapping typeMappings, final DeserializerProperties readProperties)
+      throws EntityProviderException, EdmException { 
+    Object result = null;
+
+    try {
+      reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_D_2007_08, name);
+      final String nullAttribute = reader.getAttributeValue(Edm.NAMESPACE_M_2007_08, FormatXml.M_NULL);
+
+      if (!(nullAttribute == null || TRUE.equals(nullAttribute) || FALSE.equals(nullAttribute))) {
+        throw new EntityProviderException(EntityProviderException.COMMON);
+      }
+
+      if (TRUE.equals(nullAttribute)) {
+        if ((readProperties == null || readProperties.isValidatingFacets()) && propertyInfo.isMandatory()) {
+          throw new EntityProviderException(EntityProviderException.INVALID_PROPERTY_VALUE.addContent(name));
+        }
+        reader.nextTag();
+      } else if (propertyInfo.isComplex()) {
+        final String typeAttribute = reader.getAttributeValue(Edm.NAMESPACE_M_2007_08, FormatXml.M_TYPE);
+        if (typeAttribute != null) {
+          final String expectedTypeAttributeValue =
+              propertyInfo.getType().getNamespace() + Edm.DELIMITER + propertyInfo.getType().getName();
+          if (!expectedTypeAttributeValue.equals(typeAttribute)) { //NOSONAR
+            throw new EntityProviderException(EntityProviderException.INVALID_COMPLEX_TYPE.addContent(
+                expectedTypeAttributeValue).addContent(typeAttribute));
+          }
+        }
+
+        reader.nextTag();
+        Map<String, Object> name2Value = new HashMap<String, Object>();
+        while (reader.hasNext() && !reader.isEndElement()) {
+          final String childName = reader.getLocalName();
+          final EntityPropertyInfo childProperty =
+              ((EntityComplexPropertyInfo) propertyInfo).getPropertyInfo(childName);
+          if (childProperty == null) { //NOSONAR
+            throw new EntityProviderException(EntityProviderException.INVALID_PROPERTY.addContent(childName));
+          }
+          final Object value = readStartedElement(reader, childName, childProperty,
+              typeMappings.getEntityTypeMapping(name), readProperties);
+          name2Value.put(childName, value);
+          reader.nextTag();
+        }
+        result = name2Value;
+      } else {
+        result = convert(propertyInfo, reader.getElementText(), typeMappings.getMappingClass(name), readProperties);
+      }
+      reader.require(XMLStreamConstants.END_ELEMENT, Edm.NAMESPACE_D_2007_08, name);
+
+      return result;
+    } catch (XMLStreamException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass()
+          .getSimpleName()), e);
+    }
+  }
+
+  private Object convert(final EntityPropertyInfo property, final String value, final Class<?> typeMapping,
+      final DeserializerProperties readProperties) throws EdmSimpleTypeException {
+    final EdmSimpleType type = (EdmSimpleType) property.getType();
+    return type.valueOfString(value, EdmLiteralKind.DEFAULT,
+        readProperties == null || readProperties.isValidatingFacets() ? property.getFacets() : null,
+        typeMapping == null ? type.getDefaultType() : typeMapping);
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/serializer/AtomEntryEntitySerializer.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/serializer/AtomEntryEntitySerializer.java b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/serializer/AtomEntryEntitySerializer.java
new file mode 100644
index 0000000..5881813
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/serializer/AtomEntryEntitySerializer.java
@@ -0,0 +1,669 @@
+/*******************************************************************************
+ * 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.client.core.ep.serializer;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.net.URISyntaxException;
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.Map.Entry;
+
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmCustomizableFeedMappings;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmFacets;
+import org.apache.olingo.odata2.api.edm.EdmLiteralKind;
+import org.apache.olingo.odata2.api.edm.EdmMapping;
+import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
+import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
+import org.apache.olingo.odata2.api.edm.EdmSimpleType;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeException;
+import org.apache.olingo.odata2.api.edm.EdmTargetPath;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.client.api.ep.Entity;
+import org.apache.olingo.odata2.client.api.ep.EntityCollection;
+import org.apache.olingo.odata2.client.api.ep.EntityCollectionSerializerProperties;
+import org.apache.olingo.odata2.client.api.ep.EntitySerializerProperties;
+import org.apache.olingo.odata2.core.commons.ContentType;
+import org.apache.olingo.odata2.core.commons.Encoder;
+import org.apache.olingo.odata2.core.edm.EdmDateTimeOffset;
+import org.apache.olingo.odata2.core.ep.EntityProviderProducerException;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityInfoAggregator;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityPropertyInfo;
+import org.apache.olingo.odata2.core.ep.util.FormatXml;
+
+/**
+ * Serializes an ATOM entry.
+ * 
+ */
+public class AtomEntryEntitySerializer {
+  private final EntitySerializerProperties properties;
+  private static final String VALUE = "/$value";
+
+  /**
+   * 
+   * @param properties
+   */
+  public AtomEntryEntitySerializer(final EntitySerializerProperties properties) {
+    this.properties = properties == null ? EntitySerializerProperties.serviceRoot(null).build() : properties;
+  }
+
+  /**
+   * This serializes the xml payload entry
+   * @param writer
+   * @param eia
+   * @param data
+   * @param isRootElement
+   * @param isFeedPart
+   * @throws EntityProviderException
+   */
+  public void append(final XMLStreamWriter writer, final EntityInfoAggregator eia, final Entity data,
+      final boolean isRootElement, final boolean isFeedPart) throws EntityProviderException {
+
+    try {
+      if (properties.getServiceRoot() == null) {
+        throw new EntityProviderProducerException(EntityProviderException.MANDATORY_WRITE_PROPERTY);
+      }
+      writer.writeStartElement(FormatXml.ATOM_ENTRY);
+
+      if (isRootElement) {
+        writer.writeDefaultNamespace(Edm.NAMESPACE_ATOM_2005);
+        writer.writeNamespace(Edm.PREFIX_M, Edm.NAMESPACE_M_2007_08);
+        writer.writeNamespace(Edm.PREFIX_D, Edm.NAMESPACE_D_2007_08);
+      }
+      if (!isFeedPart) {
+        writer.writeAttribute(Edm.PREFIX_XML, Edm.NAMESPACE_XML_1998, FormatXml.XML_BASE, properties.getServiceRoot()
+            .toASCIIString());
+      }
+
+      String selfLink = null;
+      if (properties.isIncludeMetadata()) {
+        // write all atom infos (mandatory and optional)
+        selfLink = createSelfLink(eia, data.getProperties(), null, properties.isKeyAutoGenerated(), false);
+        appendAtomMandatoryParts(writer, eia, data.getProperties());
+        appendAtomOptionalParts(writer, eia, data.getProperties());
+        appendAtomEditLink(writer, eia, selfLink);
+        if (eia.getEntityType().hasStream()) {
+          appendAtomContentLink(writer, eia, data.getProperties(), selfLink);
+        }
+      }
+
+      appendNavigationLinks(writer, eia, data);
+      appendCustomProperties(writer, eia, data.getProperties());
+
+      if (eia.getEntityType().hasStream()) {
+        if (properties.isIncludeMetadata()) {
+          appendAtomContentPart(writer, eia, data.getProperties(), selfLink);
+        }
+        appendProperties(writer, eia, data.getProperties());
+      } else {
+        writer.writeStartElement(FormatXml.ATOM_CONTENT);
+        writer.writeAttribute(FormatXml.ATOM_TYPE, ContentType.APPLICATION_XML.toString());
+        appendProperties(writer, eia, data.getProperties());
+        writer.writeEndElement();
+      }
+      writer.writeEndElement();
+      writer.flush();
+
+    } catch (XMLStreamException e) {
+      throw new EntityProviderProducerException(EntityProviderException.COMMON, e);
+    } catch (EdmException e) {
+      throw new EntityProviderProducerException(e.getMessageReference(), e);
+    } catch (URISyntaxException e) {
+      throw new EntityProviderProducerException(EntityProviderException.COMMON, e);
+    }
+  }
+
+  @SuppressWarnings("unchecked")
+  private void appendNavigationLinks(final XMLStreamWriter writer, //NOSONAR
+      final EntityInfoAggregator eia,
+      final Entity data) 
+      throws EntityProviderException, EdmException, URISyntaxException, XMLStreamException { 
+
+    for (Entry<String, Object> entry : data.getNavigations().entrySet()) {
+      final EntityInfoAggregator targetEntityInfo = EntityInfoAggregator.create(
+          eia.getEntitySet().getRelatedEntitySet(
+              (EdmNavigationProperty) eia.getEntityType().getProperty(entry.getKey())));
+      final boolean isFeed =
+          (eia.getNavigationPropertyInfo(entry.getKey()).getMultiplicity() == EdmMultiplicity.MANY);
+      if (entry.getValue() == null) {
+        throw new EntityProviderProducerException(EntityProviderProducerException.NULL_VALUE);
+      } else if (entry.getValue() instanceof Map) {
+        Map<String, Object> navigationKeyMap = (Map<String, Object>) entry.getValue();
+        if (navigationKeyMap != null && !navigationKeyMap.isEmpty()) {
+          appendAtomNavigationLink(writer, createSelfLink(targetEntityInfo, navigationKeyMap, null, 
+              properties.isKeyAutoGenerated(), false), entry.getKey(), isFeed);
+          writer.writeEndElement();
+        }
+      } else if (entry.getValue() instanceof Entity) {
+        Entity navigationEntity = (Entity) entry.getValue();
+        Map<String, Object> navigationKeyMap = navigationEntity.getProperties();
+        if (navigationKeyMap != null && !navigationKeyMap.isEmpty()) {
+          String navigationPropertyName = entry.getKey();
+          String selfLink = createSelfLink(eia, data.getProperties(), navigationPropertyName,
+              properties.isKeyAutoGenerated(), false);
+          appendNavigationLink(writer, selfLink, navigationPropertyName);
+
+          writer.writeAttribute(FormatXml.ATOM_TYPE, ContentType.APPLICATION_ATOM_XML_ENTRY.toString());
+          appendInlineEntry(writer, navigationPropertyName, eia, data);
+          writer.writeEndElement();
+
+        }
+      } else if (entry.getValue() instanceof EntityCollection) {
+        String navigationPropertyName = entry.getKey();
+        String selfLink = createSelfLink(eia, data.getProperties(), navigationPropertyName, 
+            properties.isKeyAutoGenerated(), false);
+        if (!((EntityCollection) entry.getValue()).getEntities().isEmpty()) {
+          appendNavigationLink(writer, selfLink, navigationPropertyName);
+
+          writer.writeAttribute(FormatXml.ATOM_TYPE, ContentType.APPLICATION_ATOM_XML_FEED.toString());
+          appendInlineFeed(writer, navigationPropertyName, eia, data);
+          writer.writeEndElement();
+        }
+
+      } else{
+        throw new EntityProviderProducerException(EntityProviderProducerException.INCORRECT_NAVIGATION_TYPE);
+        
+      }
+    }
+  }
+
+  private void appendNavigationLink(XMLStreamWriter writer, String selfLink, String navigationPropertyName)
+      throws XMLStreamException {
+
+    writer.writeStartElement(FormatXml.ATOM_LINK);
+    writer.writeAttribute(FormatXml.ATOM_HREF, selfLink);
+    writer.writeAttribute(FormatXml.ATOM_REL, Edm.NAMESPACE_REL_2007_08 + navigationPropertyName);
+    writer.writeAttribute(FormatXml.ATOM_TITLE, navigationPropertyName);
+  }
+
+  private void appendCustomProperties(final XMLStreamWriter writer, final EntityInfoAggregator eia,
+      final Map<String, Object> data) throws EntityProviderException {
+    List<String> noneSyndicationTargetPaths = eia.getNoneSyndicationTargetPathNames();
+    for (String tpName : noneSyndicationTargetPaths) {
+      EntityPropertyInfo info = eia.getTargetPathInfo(tpName);
+      final String name = info.getName();
+      XmlPropertyEntitySerializer aps = new XmlPropertyEntitySerializer(properties);
+      aps.appendCustomProperty(writer, name, info, data.get(name));
+    }
+  }
+
+  private void appendAtomNavigationLink(final XMLStreamWriter writer, final String target,
+      final String navigationPropertyName, final boolean isFeed) 
+          throws EntityProviderException, EdmException, URISyntaxException { //NOSONAR
+    try {
+      writer.writeStartElement(FormatXml.ATOM_LINK);
+      writer.writeAttribute(FormatXml.ATOM_HREF, target);
+      writer.writeAttribute(FormatXml.ATOM_REL, Edm.NAMESPACE_REL_2007_08 + navigationPropertyName);
+      writer.writeAttribute(FormatXml.ATOM_TITLE, navigationPropertyName);
+      if (isFeed) {
+        writer.writeAttribute(FormatXml.ATOM_TYPE, ContentType.APPLICATION_ATOM_XML_FEED.toString());
+      } else {
+        writer.writeAttribute(FormatXml.ATOM_TYPE, ContentType.APPLICATION_ATOM_XML_ENTRY.toString());
+      }
+    } catch (XMLStreamException e) {
+      throw new EntityProviderProducerException(EntityProviderException.COMMON, e);
+    }
+  }
+
+  private void appendInlineFeed(final XMLStreamWriter writer, final String navigationPropertyName,
+      final EntityInfoAggregator eia, final Entity data)
+      throws EntityProviderException, XMLStreamException, EdmException {
+
+    if (eia.getNavigationPropertyNames().contains(navigationPropertyName) && 
+        data != null && data.getNavigations().containsKey(navigationPropertyName)) {
+
+        EdmNavigationProperty navProp = (EdmNavigationProperty) eia.getEntityType().getProperty(navigationPropertyName);
+
+        if (navProp == null) {
+          throw new EntityProviderProducerException(EntityProviderException.EXPANDNOTSUPPORTED);
+        }
+        EntityCollection inlineData;
+        inlineData = (EntityCollection) data.getNavigation(navigationPropertyName);
+        if (inlineData == null) {
+          inlineData = new EntityCollection();
+        }
+
+        if (inlineData.getEntities().isEmpty()) {
+          return;
+        }
+        writer.writeStartElement(Edm.NAMESPACE_M_2007_08, FormatXml.M_INLINE);
+
+        EntityCollectionSerializerProperties inlineProperties = inlineData.getCollectionProperties() == null
+            ? EntityCollectionSerializerProperties.serviceRoot(data.getWriteProperties().getServiceRoot()).build()
+            : inlineData.getCollectionProperties();
+        EdmEntitySet inlineEntitySet = eia.getEntitySet().getRelatedEntitySet(navProp);
+        AtomFeedSerializer inlineFeedProducer = new AtomFeedSerializer(inlineProperties);
+        inlineData.setCollectionProperties(inlineProperties);
+        EntityInfoAggregator inlineEia =
+            EntityInfoAggregator.create(inlineEntitySet, null);
+        inlineFeedProducer.append(writer, inlineEia, inlineData, true);
+
+        writer.writeEndElement();
+
+    }
+  }
+
+  private void appendInlineEntry(final XMLStreamWriter writer, final String navigationPropertyName,
+      final EntityInfoAggregator eia, final Entity data) throws EntityProviderException,
+      XMLStreamException, EdmException {
+
+    if (data.getNavigations() != null && data.getNavigations().containsKey(navigationPropertyName)) {
+
+      EdmNavigationProperty navProp = (EdmNavigationProperty) eia.getEntityType().getProperty(navigationPropertyName);
+
+      Entity inlineData = (Entity) data.getNavigation(navigationPropertyName);
+
+      if ((inlineData == null) || inlineData.getProperties().size() == 0) {
+        return;
+      }
+
+      writer.writeStartElement(Edm.NAMESPACE_M_2007_08, FormatXml.M_INLINE);
+      if (inlineData != null && !(inlineData.getProperties().isEmpty())) {
+        inlineData.setWriteProperties(inlineData.getWriteProperties() == null ? data.getWriteProperties() : inlineData
+            .getWriteProperties());
+        EdmEntitySet inlineEntitySet = eia.getEntitySet().getRelatedEntitySet(navProp);
+        AtomEntryEntitySerializer inlineProducer = new AtomEntryEntitySerializer(inlineData.getWriteProperties());
+        EntityInfoAggregator inlineEia =
+            EntityInfoAggregator.create(inlineEntitySet, null);
+        inlineProducer.append(writer, inlineEia, inlineData, false, false);
+      }
+
+      writer.writeEndElement();
+    }
+  }
+
+
+  private void appendAtomEditLink(final XMLStreamWriter writer, final EntityInfoAggregator eia,
+      final String selfLink) throws EntityProviderException {
+    try {
+      writer.writeStartElement(FormatXml.ATOM_LINK);
+      writer.writeAttribute(FormatXml.ATOM_HREF, selfLink);
+      writer.writeAttribute(FormatXml.ATOM_REL, Edm.LINK_REL_EDIT);
+      writer.writeAttribute(FormatXml.ATOM_TITLE, eia.getEntityType().getName());
+      writer.writeEndElement();
+    } catch (XMLStreamException e) {
+      throw new EntityProviderProducerException(EntityProviderException.COMMON, e);
+    } catch (EdmException e) {
+      throw new EntityProviderProducerException(e.getMessageReference(), e);
+    }
+  }
+
+  private void appendAtomContentLink(final XMLStreamWriter writer, final EntityInfoAggregator eia,
+      final Map<String, Object> data, final String selfLink) throws EntityProviderException, EdmException {
+    try {
+      String mediaResourceMimeType = null;
+      EdmMapping entityTypeMapping = eia.getEntityType().getMapping();
+      if (entityTypeMapping != null) {
+        String mediaResourceMimeTypeKey = entityTypeMapping.getMediaResourceMimeTypeKey();
+        if (mediaResourceMimeTypeKey != null) {
+          mediaResourceMimeType = (String) data.get(mediaResourceMimeTypeKey);
+        }
+      }
+      if (mediaResourceMimeType == null) {
+        mediaResourceMimeType = ContentType.APPLICATION_OCTET_STREAM.toString();
+      }
+
+      writer.writeStartElement(FormatXml.ATOM_LINK);
+      writer.writeAttribute(FormatXml.ATOM_HREF, selfLink + VALUE);
+      writer.writeAttribute(FormatXml.ATOM_REL, Edm.LINK_REL_EDIT_MEDIA);
+      writer.writeAttribute(FormatXml.ATOM_TYPE, mediaResourceMimeType);
+      writer.writeEndElement();
+    } catch (XMLStreamException e) {
+      throw new EntityProviderProducerException(EntityProviderException.COMMON, e);
+    }
+  }
+
+  private void appendAtomContentPart(final XMLStreamWriter writer, final EntityInfoAggregator eia,
+      final Map<String, Object> data, final String selfLink) throws EntityProviderException, EdmException {
+    try {
+
+      EdmMapping entityTypeMapping = eia.getEntityType().getMapping();
+      String self = null;
+      String mediaResourceMimeType = null;
+
+      if (entityTypeMapping != null) {
+        String mediaResourceSourceKey = entityTypeMapping.getMediaResourceSourceKey();
+        if (mediaResourceSourceKey != null) {
+          self = (String) data.get(mediaResourceSourceKey);
+        }
+        if (self == null) {
+          self = selfLink + VALUE;
+        }
+        String mediaResourceMimeTypeKey = entityTypeMapping.getMediaResourceMimeTypeKey();
+        if (mediaResourceMimeTypeKey != null) {
+          mediaResourceMimeType = (String) data.get(mediaResourceMimeTypeKey);
+        }
+        if (mediaResourceMimeType == null) {
+          mediaResourceMimeType = ContentType.APPLICATION_OCTET_STREAM.toString();
+        }
+      } else {
+        self = selfLink + VALUE;
+        mediaResourceMimeType = ContentType.APPLICATION_OCTET_STREAM.toString();
+      }
+
+      writer.writeStartElement(FormatXml.ATOM_CONTENT);
+      writer.writeAttribute(FormatXml.ATOM_TYPE, mediaResourceMimeType);
+      writer.writeAttribute(FormatXml.ATOM_SRC, self);
+      writer.writeEndElement();
+    } catch (XMLStreamException e) {
+      throw new EntityProviderProducerException(EntityProviderException.COMMON, e);
+    }
+  }
+
+  private void appendAtomMandatoryParts(final XMLStreamWriter writer, final EntityInfoAggregator eia,
+      final Map<String, Object> data) throws EntityProviderException {
+    try {
+      writer.writeStartElement(FormatXml.ATOM_ID);
+      String idlocation = properties.getServiceRoot().toASCIIString() + createSelfLink(
+          eia, data, null, properties.isKeyAutoGenerated(), true);;
+      writer.writeCharacters(idlocation);
+      writer.writeEndElement();
+
+      writer.writeStartElement(FormatXml.ATOM_TITLE);
+      writer.writeAttribute(FormatXml.ATOM_TYPE, FormatXml.ATOM_TEXT);
+      EntityPropertyInfo titleInfo = eia.getTargetPathInfo(EdmTargetPath.SYNDICATION_TITLE);
+      if (titleInfo != null) {
+        EdmSimpleType st = (EdmSimpleType) titleInfo.getType();
+        Object object = data.get(titleInfo.getName());
+        String title = null;
+        try { //NOSONAR
+          title = st.valueToString(object, EdmLiteralKind.DEFAULT, titleInfo.getFacets());
+        } catch (EdmSimpleTypeException e) {
+          throw new EntityProviderProducerException(EdmSimpleTypeException.getMessageReference(
+              e.getMessageReference()).updateContent(e.getMessageReference().getContent(), titleInfo.getName()), e);
+        }
+        if (title != null) {
+          writer.writeCharacters(title);
+        }
+      } else {
+        writer.writeCharacters(eia.getEntitySetName());
+      }
+      writer.writeEndElement();
+
+      writer.writeStartElement(FormatXml.ATOM_UPDATED);
+
+      writer.writeCharacters(getUpdatedString(eia, data));
+
+      writer.writeEndElement();
+    } catch (XMLStreamException e) {
+      throw new EntityProviderProducerException(EntityProviderException.COMMON, e);
+    } catch (EdmSimpleTypeException e) {
+      throw new EntityProviderProducerException(e.getMessageReference(), e);
+    }
+  }
+
+  String getUpdatedString(final EntityInfoAggregator eia, final Map<String, Object> data)
+      throws EdmSimpleTypeException, EntityProviderProducerException {
+    Object updateDate = null;
+    EdmFacets updateFacets = null;
+    EntityPropertyInfo updatedInfo = eia.getTargetPathInfo(EdmTargetPath.SYNDICATION_UPDATED);
+    if (updatedInfo != null) {
+      updateDate = data.get(updatedInfo.getName());
+      if (updateDate != null) {
+        updateFacets = updatedInfo.getFacets();
+      }
+    }
+    if (updateDate == null) {
+      updateDate = new Date();
+    }
+    try {
+      return EdmDateTimeOffset.getInstance().valueToString(updateDate, EdmLiteralKind.DEFAULT, updateFacets);
+    } catch (final EdmSimpleTypeException e) {
+      throw new EntityProviderProducerException(
+          EdmSimpleTypeException.getMessageReference(e.getMessageReference()).
+          updateContent(e.getMessageReference().getContent(),
+              updatedInfo == null ? null : updatedInfo.getName()), e);
+    }
+  }
+
+  private String getTargetPathValue(final EntityInfoAggregator eia, final String targetPath,
+      final Map<String, Object> data) throws EntityProviderException {
+    EntityPropertyInfo info = null;
+    try {
+      info = eia.getTargetPathInfo(targetPath);
+      if (info != null) {
+        EdmSimpleType type = (EdmSimpleType) info.getType();
+        Object value = data.get(info.getName());
+        return type.valueToString(value, EdmLiteralKind.DEFAULT, info.getFacets());
+      }
+      return null;
+    } catch (final EdmSimpleTypeException e) {
+      throw new EntityProviderProducerException(
+          EdmSimpleTypeException.getMessageReference(e.getMessageReference()).
+          updateContent(e.getMessageReference().getContent(), info.getName()), e);
+    }
+  }
+
+  private void appendAtomOptionalParts(final XMLStreamWriter writer, final EntityInfoAggregator eia,
+      final Map<String, Object> data) throws EntityProviderException {
+    try {
+      String authorEmail = getTargetPathValue(eia, EdmTargetPath.SYNDICATION_AUTHOREMAIL, data);
+      String authorName = getTargetPathValue(eia, EdmTargetPath.SYNDICATION_AUTHORNAME, data);
+      String authorUri = getTargetPathValue(eia, EdmTargetPath.SYNDICATION_AUTHORURI, data);
+      if (authorEmail != null || authorName != null || authorUri != null) {
+        writer.writeStartElement(FormatXml.ATOM_AUTHOR);
+        appendAtomOptionalPart(writer, FormatXml.ATOM_AUTHOR_NAME, authorName, false);
+        appendAtomOptionalPart(writer, FormatXml.ATOM_AUTHOR_EMAIL, authorEmail, false);
+        appendAtomOptionalPart(writer, FormatXml.ATOM_AUTHOR_URI, authorUri, false);
+        writer.writeEndElement();
+      }
+
+      String summary = getTargetPathValue(eia, EdmTargetPath.SYNDICATION_SUMMARY, data);
+      appendAtomOptionalPart(writer, FormatXml.ATOM_SUMMARY, summary, true);
+
+      String contributorName = getTargetPathValue(eia, EdmTargetPath.SYNDICATION_CONTRIBUTORNAME, data);
+      String contributorEmail = getTargetPathValue(eia, EdmTargetPath.SYNDICATION_CONTRIBUTOREMAIL, data);
+      String contributorUri = getTargetPathValue(eia, EdmTargetPath.SYNDICATION_CONTRIBUTORURI, data);
+      if (contributorEmail != null || contributorName != null || contributorUri != null) {
+        writer.writeStartElement(FormatXml.ATOM_CONTRIBUTOR);
+        appendAtomOptionalPart(writer, FormatXml.ATOM_CONTRIBUTOR_NAME, contributorName, false);
+        appendAtomOptionalPart(writer, FormatXml.ATOM_CONTRIBUTOR_EMAIL, contributorEmail, false);
+        appendAtomOptionalPart(writer, FormatXml.ATOM_CONTRIBUTOR_URI, contributorUri, false);
+        writer.writeEndElement();
+      }
+
+      String rights = getTargetPathValue(eia, EdmTargetPath.SYNDICATION_RIGHTS, data);
+      appendAtomOptionalPart(writer, FormatXml.ATOM_RIGHTS, rights, true);
+      String published = getTargetPathValue(eia, EdmTargetPath.SYNDICATION_PUBLISHED, data);
+      appendAtomOptionalPart(writer, FormatXml.ATOM_PUBLISHED, published, false);
+
+      String term = eia.getEntityType().getNamespace() + Edm.DELIMITER + eia.getEntityType().getName();
+      writer.writeStartElement(FormatXml.ATOM_CATEGORY);
+      writer.writeAttribute(FormatXml.ATOM_CATEGORY_TERM, term);
+      writer.writeAttribute(FormatXml.ATOM_CATEGORY_SCHEME, Edm.NAMESPACE_SCHEME_2007_08);
+      writer.writeEndElement();
+    } catch (XMLStreamException e) {
+      throw new EntityProviderProducerException(EntityProviderException.COMMON, e);
+    } catch (EdmException e) {
+      throw new EntityProviderProducerException(e.getMessageReference(), e);
+    }
+  }
+
+  private void appendAtomOptionalPart(final XMLStreamWriter writer, final String name, final String value,
+      final boolean writeType) throws EntityProviderException {
+    try {
+      if (value != null) {
+        writer.writeStartElement(name);
+        if (writeType) {
+          writer.writeAttribute(FormatXml.ATOM_TYPE, FormatXml.ATOM_TEXT);
+        }
+        writer.writeCharacters(value);
+        writer.writeEndElement();
+      }
+    } catch (XMLStreamException e) {
+      throw new EntityProviderProducerException(EntityProviderException.COMMON, e);
+    }
+  }
+
+  static String createSelfLink(final EntityInfoAggregator eia, final Map<String, Object> data, final String extension, 
+      boolean isKeyAutoGenerated, boolean isIdTag)
+      throws EntityProviderException {
+    StringBuilder sb = new StringBuilder();
+    if (!eia.isDefaultEntityContainer()) {
+      sb.append(Encoder.encode(eia.getEntityContainerName())).append(Edm.DELIMITER);
+    }
+    sb.append(Encoder.encode(eia.getEntitySetName()));
+
+    String keyValue = createEntryKey(eia, data, isKeyAutoGenerated, isIdTag);
+    if (isIdTag && isKeyAutoGenerated && "".equals(keyValue) && keyValue.length() == 0) {
+      sb.append(extension == null ? "" : ("/" + extension));
+    } else {
+      sb.append("(").append(keyValue).append(")").
+      append(extension == null ? "" : ("/" + extension));
+    }
+    return sb.toString();
+  }
+
+  private static String createEntryKey(final EntityInfoAggregator entityInfo, final Map<String, Object> data, 
+      boolean isKeyAutoGenerated, boolean isIdTag)
+      throws EntityProviderException {
+    final List<EntityPropertyInfo> keyPropertyInfos = entityInfo.getKeyPropertyInfos();
+
+    StringBuilder keys = new StringBuilder();
+    for (final EntityPropertyInfo keyPropertyInfo : keyPropertyInfos) {
+      if (keys.length() > 0) {
+        keys.append(',');
+      }
+
+      final String name = keyPropertyInfo.getName();
+      if (keyPropertyInfos.size() > 1) {
+        keys.append(Encoder.encode(name)).append('=');
+      }
+
+      final EdmSimpleType type = (EdmSimpleType) keyPropertyInfo.getType();
+      try {
+        String keyValue = null;
+        if (isKeyAutoGenerated && data.get(name) == null) {
+          if (isIdTag) {
+            keyValue = "";
+          } else {
+            Object value = fetchDefaultValue(type.getDefaultType());
+            keyValue = Encoder.encode(type.valueToString(value, EdmLiteralKind.URI,
+                keyPropertyInfo.getFacets()));
+          }
+        } else {
+          keyValue = Encoder.encode(type.valueToString(data.get(name), EdmLiteralKind.URI,
+              keyPropertyInfo.getFacets()));
+        }
+        keys.append(keyValue);
+      } catch (final EdmSimpleTypeException e) {
+        throw new EntityProviderProducerException(
+            EdmSimpleTypeException.getMessageReference(e.getMessageReference()).
+            updateContent(e.getMessageReference().getContent(), name), e);
+      }
+    }
+
+    return keys.toString();
+  }
+
+  private static Object fetchDefaultValue(Class<?> edmType) throws EntityProviderProducerException {
+    if (edmType == boolean.class || edmType == Boolean.class) {
+        return false;
+      } else if (edmType == String.class) {
+        return "A";
+      } else if (edmType == byte.class || edmType == Byte.class) {
+        return new Byte(Byte.parseByte("0"));
+      } else if (edmType == char.class) {
+        return new Character('A');
+      } else if (edmType == short.class || edmType == Short.class) {
+        return new Short(Short.parseShort("0"));
+      } else if (edmType == int.class || edmType == Integer.class) {
+        return new Integer(0);
+      } else if (edmType == long.class || edmType == Long.class) {
+        return new Long(0L);
+      } else if (edmType == float.class || edmType == Float.class) {
+        return new Float(0.0f);
+      } else if (edmType == double.class || edmType == Double.class) {
+        return new Double(0.0d);
+      } else if (edmType == BigDecimal.class) {
+        return BigDecimal.valueOf(0.0);
+      } else if (edmType == UUID.class) {
+        return UUID.fromString("0");
+      } else if (edmType == Timestamp.class) {
+        return new Timestamp(Calendar.getInstance().getTimeInMillis());
+      } else if (edmType == Calendar.class) {
+        return Calendar.getInstance();
+      } else if (edmType == byte[].class || edmType == Byte[].class) {
+        return new byte[0];
+      } else if (edmType == Date.class) {
+        return new Date();
+      } else if (edmType == BigInteger.class) {
+        return new BigInteger("0");
+      } else if (edmType == Time.class) {
+        return new Time(0L);
+      } else {
+        throw new EntityProviderProducerException(EdmSimpleTypeException.VALUE_TYPE_NOT_SUPPORTED);
+      }
+    }
+  
+  private void appendProperties(final XMLStreamWriter writer, final EntityInfoAggregator eia,
+      final Map<String, Object> data) throws EntityProviderException {
+    try {
+      {
+        if (!data.isEmpty() && data.size() > 0) {
+          writer.writeStartElement(Edm.NAMESPACE_M_2007_08, FormatXml.M_PROPERTIES);
+          for (String propertyName : eia.getPropertyNames()) {
+            if (data.containsKey(propertyName)) {
+              appendPropertyNameValue(writer, eia, data, propertyName);
+            }
+          }
+          writer.writeEndElement();
+        }
+      }
+    } catch (XMLStreamException e) {
+      throw new EntityProviderProducerException(EntityProviderException.COMMON, e);
+    }
+  }
+
+  /**
+   * @param writer
+   * @param eia
+   * @param data
+   * @param propertyName
+   * @throws EntityProviderException
+   */
+  private void appendPropertyNameValue(final XMLStreamWriter writer, final EntityInfoAggregator eia,
+      final Map<String, Object> data, String propertyName) throws EntityProviderException {
+    EntityPropertyInfo propertyInfo = eia.getPropertyInfo(propertyName);
+    if (isNotMappedViaCustomMapping(propertyInfo)) {
+      Object value = data.get(propertyName);
+      XmlPropertyEntitySerializer aps = new XmlPropertyEntitySerializer(properties);
+      aps.append(writer, propertyInfo.getName(), propertyInfo, value);
+    }
+  }
+
+  private boolean isNotMappedViaCustomMapping(final EntityPropertyInfo propertyInfo) {
+    EdmCustomizableFeedMappings customMapping = propertyInfo.getCustomMapping();
+    if (customMapping != null && customMapping.isFcKeepInContent() != null) {
+      return customMapping.isFcKeepInContent();
+    }
+    return true;
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/serializer/AtomFeedSerializer.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/serializer/AtomFeedSerializer.java b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/serializer/AtomFeedSerializer.java
new file mode 100644
index 0000000..8e4e615
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/serializer/AtomFeedSerializer.java
@@ -0,0 +1,183 @@
+/*******************************************************************************
+ * 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.client.core.ep.serializer;
+
+import java.net.URI;
+import java.util.Date;
+
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmFacets;
+import org.apache.olingo.odata2.api.edm.EdmLiteralKind;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeException;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.client.api.ep.Entity;
+import org.apache.olingo.odata2.client.api.ep.EntityCollection;
+import org.apache.olingo.odata2.client.api.ep.EntityCollectionSerializerProperties;
+import org.apache.olingo.odata2.client.api.ep.EntitySerializerProperties;
+import org.apache.olingo.odata2.core.commons.Encoder;
+import org.apache.olingo.odata2.core.edm.EdmDateTimeOffset;
+import org.apache.olingo.odata2.core.ep.EntityProviderProducerException;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityInfoAggregator;
+import org.apache.olingo.odata2.core.ep.util.FormatXml;
+
+/**
+ * Serializes an ATOM feed.
+ * 
+ */
+public class AtomFeedSerializer {
+
+  private final EntityCollectionSerializerProperties properties;
+
+  /**
+   * 
+   * @param properties
+   */
+  public AtomFeedSerializer(final EntityCollectionSerializerProperties properties) {
+    this.properties = properties == null ? 
+        EntityCollectionSerializerProperties.serviceRoot(null).build() : 
+          properties;
+  }
+ 
+  /**
+   * This serializes the xml payload feed
+   * @param writer
+   * @param eia
+   * @param data
+   * @param isInline
+   * @throws EntityProviderException
+   */
+  public void append(final XMLStreamWriter writer, final EntityInfoAggregator eia,
+      final EntityCollection data, final boolean isInline) throws EntityProviderException {
+    try {
+      if (properties.getServiceRoot() == null) {
+        throw new EntityProviderProducerException(EntityProviderException.MANDATORY_WRITE_PROPERTY);
+      }
+      
+      writer.writeStartElement(FormatXml.ATOM_FEED);
+      if (!isInline) {
+        writer.writeDefaultNamespace(Edm.NAMESPACE_ATOM_2005);
+        writer.writeNamespace(Edm.PREFIX_M, Edm.NAMESPACE_M_2007_08);
+        writer.writeNamespace(Edm.PREFIX_D, Edm.NAMESPACE_D_2007_08);
+        
+      }
+      writer.writeAttribute(Edm.PREFIX_XML, Edm.NAMESPACE_XML_1998, FormatXml.XML_BASE, properties.getServiceRoot()
+          .toASCIIString());
+
+      // write all atom infos (mandatory and optional)
+      appendAtomMandatoryParts(writer, eia);
+      appendAtomSelfLink(writer, eia);
+    
+
+      appendEntries(writer, eia, data);
+
+     
+
+   
+      writer.writeEndElement();
+    } catch (XMLStreamException e) {
+      throw new EntityProviderProducerException(EntityProviderException.COMMON, e);
+    }
+  }
+
+  private void appendEntries(final XMLStreamWriter writer, final EntityInfoAggregator eia,
+      final EntityCollection data) throws EntityProviderException {
+    AtomEntryEntitySerializer entryProvider;
+    for (Entity singleEntryData : data.getEntities()) {
+      entryProvider = singleEntryData.getWriteProperties() == null? data.getGlobalEntityProperties() == null ?
+          new AtomEntryEntitySerializer
+          (EntitySerializerProperties.serviceRoot(data.getCollectionProperties().getServiceRoot()).build()) :
+            new AtomEntryEntitySerializer(data.getGlobalEntityProperties()):
+            new AtomEntryEntitySerializer(singleEntryData.getWriteProperties());
+       entryProvider.append(writer, eia, singleEntryData, false, true);
+    }
+  }
+
+
+  private void appendAtomSelfLink(final XMLStreamWriter writer, final EntityInfoAggregator eia)
+      throws EntityProviderException {
+
+    URI self = properties.getSelfLink();
+    String selfLink = "";
+    if (self == null) {
+      selfLink = createSelfLink(eia);
+    } else {
+      selfLink = self.toASCIIString();
+    }
+    try {
+      writer.writeStartElement(FormatXml.ATOM_LINK);
+      writer.writeAttribute(FormatXml.ATOM_HREF, selfLink);
+      writer.writeAttribute(FormatXml.ATOM_REL, Edm.LINK_REL_SELF);
+      writer.writeAttribute(FormatXml.ATOM_TITLE, eia.getEntitySetName());
+      writer.writeEndElement();
+    } catch (XMLStreamException e) {
+      throw new EntityProviderProducerException(EntityProviderException.COMMON, e);
+    }
+  }
+
+  private String createSelfLink(final EntityInfoAggregator eia) {
+    StringBuilder sb = new StringBuilder();
+    if (!eia.isDefaultEntityContainer()) {
+      final String entityContainerName = Encoder.encode(eia.getEntityContainerName());
+      sb.append(entityContainerName).append(Edm.DELIMITER);
+    }
+    final String entitySetName = Encoder.encode(eia.getEntitySetName());
+    sb.append(entitySetName);
+    return sb.toString();
+  }
+
+  private void appendAtomMandatoryParts(final XMLStreamWriter writer, final EntityInfoAggregator eia)
+      throws EntityProviderException {
+    try {
+      writer.writeStartElement(FormatXml.ATOM_ID);
+      writer.writeCharacters(createAtomId(eia));
+      writer.writeEndElement();
+
+      writer.writeStartElement(FormatXml.ATOM_TITLE);
+      writer.writeAttribute(FormatXml.M_TYPE, FormatXml.ATOM_TEXT);
+      writer.writeCharacters(eia.getEntitySetName());
+      writer.writeEndElement();
+
+      writer.writeStartElement(FormatXml.ATOM_UPDATED);
+
+      Object updateDate = null;
+      EdmFacets updateFacets = null;
+      updateDate = new Date();
+      writer.writeCharacters(EdmDateTimeOffset.getInstance().valueToString(updateDate, EdmLiteralKind.DEFAULT,
+          updateFacets));
+      writer.writeEndElement();
+
+      writer.writeStartElement(FormatXml.ATOM_AUTHOR);
+      writer.writeStartElement(FormatXml.ATOM_AUTHOR_NAME);
+      writer.writeEndElement();
+      writer.writeEndElement();
+
+    } catch (XMLStreamException e) {
+      throw new EntityProviderProducerException(EntityProviderException.COMMON, e);
+    } catch (EdmSimpleTypeException e) {
+      throw new EntityProviderProducerException(e.getMessageReference(), e);
+    }
+  }
+
+  private String createAtomId(final EntityInfoAggregator eia) throws EntityProviderException {
+    return properties.getServiceRoot() + createSelfLink(eia);
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/serializer/JsonEntryEntitySerializer.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/serializer/JsonEntryEntitySerializer.java b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/serializer/JsonEntryEntitySerializer.java
new file mode 100644
index 0000000..b727538
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/serializer/JsonEntryEntitySerializer.java
@@ -0,0 +1,309 @@
+/*******************************************************************************
+ * 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.client.core.ep.serializer;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmEntityType;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmMapping;
+import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
+import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.client.api.ep.Entity;
+import org.apache.olingo.odata2.client.api.ep.EntityCollection;
+import org.apache.olingo.odata2.client.api.ep.EntityCollectionSerializerProperties;
+import org.apache.olingo.odata2.client.api.ep.EntitySerializerProperties;
+import org.apache.olingo.odata2.core.commons.ContentType;
+import org.apache.olingo.odata2.core.ep.EntityProviderProducerException;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityInfoAggregator;
+import org.apache.olingo.odata2.core.ep.util.FormatJson;
+import org.apache.olingo.odata2.core.ep.util.JsonStreamWriter;
+
+/**
+ * Producer for writing an entity in JSON, also usable for function imports
+ * returning a single instance of an entity type.
+ * 
+ */
+public class JsonEntryEntitySerializer {
+
+  private final EntitySerializerProperties properties;
+  private String location;
+  private String idlocation;
+  private JsonStreamWriter jsonStreamWriter;
+  private static final String VALUE = "/$value";
+
+  /**
+   * 
+   * @param properties
+   * @throws EntityProviderException
+   */
+  public JsonEntryEntitySerializer(final EntitySerializerProperties properties) {
+    this.properties = properties == null ? EntitySerializerProperties.serviceRoot(null).build() : properties;
+  }
+
+  /**
+   * This serializes the json payload entry
+   * @param writer
+   * @param entityInfo
+   * @param data
+   * @param isRootElement
+   * @throws EntityProviderException
+   */
+  public void append(final Writer writer, final EntityInfoAggregator entityInfo, final Entity data) 
+      throws EntityProviderException {
+   if (data == null) {
+     throw new EntityProviderException(EntityProviderException.NULL_VALUE);
+   }
+    final EdmEntityType type = entityInfo.getEntityType();
+
+    try {
+      jsonStreamWriter = new JsonStreamWriter(writer);
+     
+      jsonStreamWriter.beginObject();
+
+      boolean containsMetadata = false;
+      if (properties.isIncludeMetadata()) {
+        writeMetadata(entityInfo, data.getProperties(), type);
+        containsMetadata = true;
+      } 
+      writeProperties(entityInfo, data.getProperties(), type, containsMetadata);
+
+      writeNavigationProperties(writer, entityInfo, data.getNavigations(), type);
+      jsonStreamWriter.endObject();
+      
+      writer.flush();
+
+    } catch (final IOException e) {
+      throw new EntityProviderProducerException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass()
+          .getSimpleName()), e);
+    } catch (final EdmException e) {
+      throw new EntityProviderProducerException(e.getMessageReference(), e);
+    }
+  }
+
+  private void writeNavigationProperties(final Writer writer, final EntityInfoAggregator entityInfo,
+      final Map<String, Object> data,
+      final EdmEntityType type) throws EdmException, EntityProviderException, IOException {
+    for (final String navigationPropertyName : type.getNavigationPropertyNames()) {
+      if (data.containsKey(navigationPropertyName)) {
+        if (data.get(navigationPropertyName) == null) {
+          throw new EntityProviderException(EntityProviderException.NULL_VALUE);
+        }
+        if (data.get(navigationPropertyName) instanceof Entity || 
+            data.get(navigationPropertyName) instanceof EntityCollection) {
+          jsonStreamWriter.separator();
+          jsonStreamWriter.name(navigationPropertyName);
+          writeExpandedNavigationProperty(writer, entityInfo, data, type, navigationPropertyName);
+        } else if (data.get(navigationPropertyName) instanceof Map<?,?>){
+          writeNavigationLinks(entityInfo, data);
+        } else {
+          throw new EntityProviderException(EntityProviderException.INCORRECT_NAVIGATION_TYPE);
+        }
+      }
+    }
+  }
+
+  private void writeExpandedNavigationProperty(final Writer writer, final EntityInfoAggregator entityInfo,
+      final Map<String, Object> data,
+      final EdmEntityType type, final String navigationPropertyName) throws EdmException, EntityProviderException,
+      IOException {
+    
+    final EdmNavigationProperty navigationProperty = (EdmNavigationProperty) type.getProperty(navigationPropertyName);
+    final boolean isFeed = navigationProperty.getMultiplicity() == EdmMultiplicity.MANY;
+    final EdmEntitySet entitySet = entityInfo.getEntitySet();
+    final EdmEntitySet inlineEntitySet = entitySet.getRelatedEntitySet(navigationProperty);
+
+    if (isFeed) {
+      EntityCollection inlineData = (EntityCollection) data.get(navigationProperty.getName());
+      
+      if(inlineData == null){
+        throw new EntityProviderException(EntityProviderException.NULL_VALUE);
+      }
+      final EntityCollectionSerializerProperties inlineProperties = inlineData.getCollectionProperties() == null ? 
+          EntityCollectionSerializerProperties.
+          serviceRoot(properties.getServiceRoot()).build() : 
+            inlineData.getCollectionProperties();
+      JsonFeedEntitySerializer jsonFeedEntityProducer = new JsonFeedEntitySerializer(inlineProperties);
+      final EntityInfoAggregator inlineEntityInfo =
+          EntityInfoAggregator.create(inlineEntitySet, null);
+      jsonFeedEntityProducer.appendAsArray(writer, inlineEntityInfo, inlineData);
+    } else {
+      Entity inlineData = (Entity) data.get(navigationProperty.getName());
+    //This statement is used for the client use case. Flag should never be set on server side
+      if(inlineData == null){
+        throw new EntityProviderException(EntityProviderException.NULL_VALUE);
+      }
+      if (inlineData != null && inlineData.getProperties() != null && 
+          !inlineData.getProperties().isEmpty()) {
+        final EntitySerializerProperties inlineProperties = inlineData.getWriteProperties() == null ?
+            EntitySerializerProperties.
+            serviceRoot(properties.getServiceRoot()).build() : inlineData.getWriteProperties();
+        final EntityInfoAggregator inlineEntityInfo =
+            EntityInfoAggregator.create(inlineEntitySet, null);
+        new JsonEntryEntitySerializer(inlineProperties).append(writer, inlineEntityInfo, inlineData);
+      } else {
+        jsonStreamWriter.beginObject();
+        jsonStreamWriter.endObject();
+      }
+    }
+   }
+
+  private void writeProperties(final EntityInfoAggregator entityInfo, final Map<String, Object> data,
+      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;
+
+    List<String> propertyNames = type.getPropertyNames();
+    for (final String propertyName : propertyNames) {
+      if (data.containsKey(propertyName)) {
+        omitComma = appendPropertyNameValue(entityInfo, data, omitComma, propertyName);
+      } 
+    }
+  }
+
+  /**
+   * @param entityInfo
+   * @param data
+   * @param omitComma
+   * @param propertyName
+   * @return
+   * @throws IOException
+   * @throws EdmException
+   * @throws EntityProviderException
+   */
+  private boolean appendPropertyNameValue(final EntityInfoAggregator entityInfo, final Map<String, Object> data,
+      boolean omitComma, String propertyName) throws IOException, EdmException, EntityProviderException {
+    if (omitComma) {
+      omitComma = false; //NOSONAR
+    } else {
+      jsonStreamWriter.separator();
+    }
+    jsonStreamWriter.name(propertyName);
+ 
+    JsonPropertyEntitySerializer.appendPropertyValue(jsonStreamWriter,
+        entityInfo.getPropertyInfo(propertyName),
+        data.get(propertyName),
+        properties.isValidatingFacets());
+    return omitComma;
+  }
+  
+  private void writeMetadata(final EntityInfoAggregator entityInfo, final Map<String, Object> data,
+      final EdmEntityType type) throws IOException, EntityProviderException, EdmException {
+    if (properties.getServiceRoot() == null) {
+      location = "";
+      idlocation = "";
+    } else {
+      location = properties.getServiceRoot().toASCIIString() +
+          AtomEntryEntitySerializer.createSelfLink(entityInfo, data, null, properties.isKeyAutoGenerated(), false);
+      idlocation = properties.getServiceRoot().toASCIIString() +
+          AtomEntryEntitySerializer.createSelfLink(entityInfo, data, null, properties.isKeyAutoGenerated(), true);
+    }
+
+    jsonStreamWriter.name(FormatJson.METADATA);
+    jsonStreamWriter.beginObject();
+    jsonStreamWriter.namedStringValue(FormatJson.ID, idlocation);
+    jsonStreamWriter.separator();
+    jsonStreamWriter.namedStringValue(FormatJson.URI, location);
+    jsonStreamWriter.separator();
+    jsonStreamWriter.namedStringValueRaw(FormatJson.TYPE, type.getNamespace() + Edm.DELIMITER + type.getName());
+    
+    if (type.hasStream()) {
+      jsonStreamWriter.separator();
+
+      EdmMapping entityTypeMapping = entityInfo.getEntityType().getMapping();
+      String mediaResourceMimeType = null;
+      String mediaSrc = null;
+
+      if (entityTypeMapping != null) {
+        String mediaResourceSourceKey = entityTypeMapping.getMediaResourceSourceKey();
+        if (mediaResourceSourceKey != null) {
+          mediaSrc = (String) data.get(mediaResourceSourceKey);
+        }
+        if (mediaSrc == null) {
+          mediaSrc = location + VALUE;
+        }
+        String mediaResourceMimeTypeKey = entityTypeMapping.getMediaResourceMimeTypeKey();
+        if (mediaResourceMimeTypeKey != null) {
+          mediaResourceMimeType = (String) data.get(mediaResourceMimeTypeKey);
+        }
+        if (mediaResourceMimeType == null) {
+          mediaResourceMimeType = ContentType.APPLICATION_OCTET_STREAM.toString();
+        }
+      } else {
+        mediaSrc = location + VALUE;
+        mediaResourceMimeType = ContentType.APPLICATION_OCTET_STREAM.toString();
+      }
+
+      jsonStreamWriter.namedStringValueRaw(FormatJson.CONTENT_TYPE, mediaResourceMimeType);
+      jsonStreamWriter.separator();
+
+      jsonStreamWriter.namedStringValue(FormatJson.MEDIA_SRC, mediaSrc);
+      jsonStreamWriter.separator();
+      jsonStreamWriter.namedStringValue(FormatJson.EDIT_MEDIA, location + VALUE);
+    }
+    jsonStreamWriter.endObject();
+  }
+
+  private String createCustomTargetLink(final EntityInfoAggregator entityInfo, final String navigationPropertyName,
+      final Map<String, Object> key) throws EntityProviderException, EdmException {
+    String target;
+    final EntityInfoAggregator targetEntityInfo = EntityInfoAggregator.create(
+        entityInfo.getEntitySet().getRelatedEntitySet(
+            (EdmNavigationProperty) entityInfo.getEntityType().getProperty(navigationPropertyName)));
+    target = (properties.getServiceRoot() == null ? "" : properties.getServiceRoot().toASCIIString())
+        + AtomEntryEntitySerializer.createSelfLink(targetEntityInfo, key, null, properties.isKeyAutoGenerated(), false);
+    return target;
+  }
+
+  private void writeNavigationLinks(final EntityInfoAggregator entityInfo,
+      Map<String, Object> navigationLinks) throws IOException, 
+  EntityProviderException, EdmException {
+    if (navigationLinks != null && !navigationLinks.isEmpty()) {
+      for (Entry<String, Object> entry : navigationLinks.entrySet()) {
+        String target = null;
+        if (entry.getValue() instanceof HashMap<?, ?>) {
+          @SuppressWarnings("unchecked")
+          Map<String, Object> navigationKeyMap = (Map<String, Object>) entry.getValue();
+          if (navigationKeyMap != null && !navigationKeyMap.isEmpty()) { //NOSONAR
+            target = createCustomTargetLink(entityInfo, entry.getKey(), navigationKeyMap);
+            jsonStreamWriter.separator();
+            jsonStreamWriter.name(entry.getKey());
+            jsonStreamWriter.beginObject()
+                .name(FormatJson.DEFERRED);
+            JsonLinkEntitySerializer.appendUri(jsonStreamWriter, target);
+            jsonStreamWriter.endObject();
+          }
+        }
+      }
+    }
+  }
+
+  public String getLocation() {
+    return location;
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/serializer/JsonFeedEntitySerializer.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/serializer/JsonFeedEntitySerializer.java b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/serializer/JsonFeedEntitySerializer.java
new file mode 100644
index 0000000..e86b6c4
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/serializer/JsonFeedEntitySerializer.java
@@ -0,0 +1,125 @@
+/*******************************************************************************
+ * 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.client.core.ep.serializer;
+
+import java.io.IOException;
+import java.io.Writer;
+
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.client.api.ep.Entity;
+import org.apache.olingo.odata2.client.api.ep.EntityCollection;
+import org.apache.olingo.odata2.client.api.ep.EntityCollectionSerializerProperties;
+import org.apache.olingo.odata2.client.api.ep.EntitySerializerProperties;
+import org.apache.olingo.odata2.core.ep.EntityProviderProducerException;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityInfoAggregator;
+import org.apache.olingo.odata2.core.ep.util.FormatJson;
+import org.apache.olingo.odata2.core.ep.util.JsonStreamWriter;
+
+/**
+ * Producer for writing an entity collection (a feed) in JSON.
+ * 
+ */
+public class JsonFeedEntitySerializer {
+
+  private final EntityCollectionSerializerProperties properties;
+
+  /**
+   * 
+   * @param properties
+   * @throws EntityProviderException
+   */
+  public JsonFeedEntitySerializer(final EntityCollectionSerializerProperties properties) {
+    this.properties = properties == null ? EntityCollectionSerializerProperties.
+        serviceRoot(null).build() : properties;
+  }
+
+  /**
+   * This serializes the json payload feed
+   * @param writer
+   * @param entityInfo
+   * @param data
+   * @throws EntityProviderException
+   */
+  public void appendAsArray(final Writer writer, final EntityInfoAggregator entityInfo,
+                            final EntityCollection data) throws EntityProviderException {
+    
+    JsonStreamWriter jsonStreamWriter = new JsonStreamWriter(writer);
+    try {
+      jsonStreamWriter.beginArray();
+      appendEntries(writer, entityInfo, data, jsonStreamWriter);
+      jsonStreamWriter.endArray();
+    } catch (final IOException e) {
+      throw new EntityProviderProducerException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass()
+          .getSimpleName()), e);
+    }
+  }
+
+  /**
+   * This serializes the json payload feed
+   * @param writer
+   * @param entityInfo
+   * @param data
+   * @param isRootElement
+   * @throws EntityProviderException
+   */
+  public void appendAsObject(final Writer writer, final EntityInfoAggregator entityInfo,
+      final EntityCollection data) throws EntityProviderException {
+    if (data == null) {
+      throw new EntityProviderException(EntityProviderException.NULL_VALUE);
+    }
+    JsonStreamWriter jsonStreamWriter = new JsonStreamWriter(writer);
+
+    try {
+      jsonStreamWriter.beginObject();
+
+      jsonStreamWriter.name(FormatJson.RESULTS)
+          .beginArray();
+
+      appendEntries(writer, entityInfo, data, jsonStreamWriter);
+
+      jsonStreamWriter.endArray();
+
+      jsonStreamWriter.endObject();
+    } catch (final IOException e) {
+      throw new EntityProviderProducerException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass()
+          .getSimpleName()), e);
+    }
+  }
+  
+  private void appendEntries(final Writer writer, final EntityInfoAggregator entityInfo,
+      final EntityCollection data, JsonStreamWriter jsonStreamWriter) throws EntityProviderException,
+      IOException {
+    boolean first = true;
+    for (Entity entryData : data.getEntities()) {
+      if (first) {
+        first = false;
+      } else {
+        jsonStreamWriter.separator();
+      }
+      EntitySerializerProperties entryProperties = entryData == null ||
+          entryData.getWriteProperties() == null ? data.getGlobalEntityProperties() != null?
+              data.getGlobalEntityProperties(): EntitySerializerProperties.
+              serviceRoot(properties.getServiceRoot()).
+              build() : entryData.getWriteProperties();
+      
+      JsonEntryEntitySerializer entryProducer = new JsonEntryEntitySerializer(entryProperties);
+      entryProducer.append(writer, entityInfo, entryData);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/serializer/JsonLinkEntitySerializer.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/serializer/JsonLinkEntitySerializer.java b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/serializer/JsonLinkEntitySerializer.java
new file mode 100644
index 0000000..cd756ce
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/serializer/JsonLinkEntitySerializer.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * 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.client.core.ep.serializer;
+
+import java.io.IOException;
+
+import org.apache.olingo.odata2.api.ep.EntityProviderWriteProperties;
+import org.apache.olingo.odata2.core.ep.util.FormatJson;
+import org.apache.olingo.odata2.core.ep.util.JsonStreamWriter;
+
+/**
+ * Producer for writing a link in JSON.
+ * 
+ */
+public class JsonLinkEntitySerializer {
+
+  private final EntityProviderWriteProperties properties; //NOSONAR
+
+  /**
+   * 
+   * @param properties
+   * @throws EntityProviderException
+   */
+  public JsonLinkEntitySerializer(final EntityProviderWriteProperties properties) {
+    this.properties = properties == null ? EntityProviderWriteProperties.serviceRoot(null).build() : properties;
+  }
+
+  protected static void appendUri(final JsonStreamWriter jsonStreamWriter, final String uri) throws IOException {
+    jsonStreamWriter.beginObject()
+        .namedStringValue(FormatJson.URI, uri)
+        .endObject();
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/serializer/JsonPropertyEntitySerializer.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/serializer/JsonPropertyEntitySerializer.java b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/serializer/JsonPropertyEntitySerializer.java
new file mode 100644
index 0000000..f759389
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/serializer/JsonPropertyEntitySerializer.java
@@ -0,0 +1,151 @@
+/*******************************************************************************
+ * 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.client.core.ep.serializer;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmFacets;
+import org.apache.olingo.odata2.api.edm.EdmLiteralKind;
+import org.apache.olingo.odata2.api.edm.EdmSimpleType;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeException;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeKind;
+import org.apache.olingo.odata2.api.edm.EdmType;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.client.api.ep.Entity;
+import org.apache.olingo.odata2.core.ep.EntityProviderProducerException;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityComplexPropertyInfo;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityPropertyInfo;
+import org.apache.olingo.odata2.core.ep.util.FormatJson;
+import org.apache.olingo.odata2.core.ep.util.JsonStreamWriter;
+
+/**
+ * Producer for writing a single simple or complex property in JSON, also usable
+ * for function imports returning a single instance of a simple or complex type.
+ * 
+ */
+public class JsonPropertyEntitySerializer {
+
+  /**
+   * Serializes a property of every entry in json payload
+   * @param writer
+   * @param propertyInfo
+   * @param value
+   * @throws EntityProviderException
+   */
+  public void append(final Writer writer, final EntityPropertyInfo propertyInfo, final Object value)
+      throws EntityProviderException {
+    JsonStreamWriter jsonStreamWriter = new JsonStreamWriter(writer);
+
+    try {
+      jsonStreamWriter.beginObject()
+          .name(FormatJson.D)
+          .beginObject();
+
+      jsonStreamWriter.name(propertyInfo.getName());
+      appendPropertyValue(jsonStreamWriter, propertyInfo.isComplex() ? (EntityComplexPropertyInfo) propertyInfo
+          : propertyInfo, value, true);
+
+      jsonStreamWriter.endObject()
+          .endObject();
+    } catch (final IOException e) {
+      throw new EntityProviderProducerException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass()
+          .getSimpleName()), e);
+    } catch (final EdmException e) {
+      throw new EntityProviderProducerException(e.getMessageReference(), e);
+    }
+  }
+
+  protected static void appendPropertyValue(final JsonStreamWriter jsonStreamWriter,
+                                            final EntityPropertyInfo propertyInfo, final Object value,
+                                            boolean validatingFacets) throws IOException, EdmException,
+      EntityProviderException { //NOSONAR
+    if (propertyInfo.isComplex()) {
+      if (value == null || value instanceof Map<?,?>) {
+        jsonStreamWriter.beginObject();
+        appendPropertyMetadata(jsonStreamWriter, propertyInfo.getType());
+        if (value == null) {
+          jsonStreamWriter.endObject();
+          return;
+        }
+        for (final EntityPropertyInfo childPropertyInfo : ((EntityComplexPropertyInfo) propertyInfo)
+            .getPropertyInfos()) {
+          final String name = childPropertyInfo.getName();
+          if ( !((Map<?,?>)value).containsKey(name)) { //NOSONAR
+            continue;
+          } 
+          jsonStreamWriter.separator();
+          jsonStreamWriter.name(name);
+          appendPropertyValue(jsonStreamWriter, childPropertyInfo,
+              value == null ? null : ((Map<?,?>) value).get(name), validatingFacets); //NOSONAR
+        }
+        jsonStreamWriter.endObject();
+      } else {
+        throw new EntityProviderProducerException(EntityProviderException.ILLEGAL_ARGUMENT
+            .addContent("A complex property must have a Map as data"));
+      }
+    } else {
+      final EdmSimpleType type = (EdmSimpleType) propertyInfo.getType();
+      final Object contentValue = value instanceof Entity ? ((Entity) value).
+          getProperties().get(propertyInfo.getName()) : value;
+      final EdmFacets facets = validatingFacets ? propertyInfo.getFacets(): null;
+      String valueAsString = null;
+      try {
+      valueAsString = type.valueToString(contentValue, EdmLiteralKind.JSON, facets);
+      } catch (EdmSimpleTypeException e) {
+        throw new EntityProviderProducerException(EdmSimpleTypeException.getMessageReference(
+            e.getMessageReference()).updateContent(e.getMessageReference().getContent(), 
+                propertyInfo.getName()), e);
+      }
+      switch (EdmSimpleTypeKind.valueOf(type.getName())) {
+      case String:
+        jsonStreamWriter.stringValue(valueAsString);
+        break;
+      case Boolean:
+      case Byte:
+      case SByte:
+      case Int16:
+      case Int32:
+        jsonStreamWriter.unquotedValue(valueAsString);
+        break;
+      case DateTime:
+      case DateTimeOffset:
+        // Although JSON escaping is (and should be) done in the JSON
+        // serializer, we backslash-escape the forward slash here explicitly
+        // because it is not required to escape it in JSON but in OData.
+        jsonStreamWriter.stringValueRaw(valueAsString == null ? null : valueAsString.replace("/", "\\/"));
+        break;
+      default:
+        jsonStreamWriter.stringValueRaw(valueAsString);
+        break;
+      }
+    }
+  }
+
+  protected static void appendPropertyMetadata(final JsonStreamWriter jsonStreamWriter, final EdmType type)
+      throws IOException, EdmException {
+    jsonStreamWriter.name(FormatJson.METADATA)
+        .beginObject()
+        .namedStringValueRaw(FormatJson.TYPE, type.getNamespace() + Edm.DELIMITER + type.getName())
+        .endObject();
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/serializer/XmlPropertyEntitySerializer.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/serializer/XmlPropertyEntitySerializer.java b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/serializer/XmlPropertyEntitySerializer.java
new file mode 100644
index 0000000..24bfc17
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/serializer/XmlPropertyEntitySerializer.java
@@ -0,0 +1,234 @@
+/*******************************************************************************
+ * 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.client.core.ep.serializer;
+
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmCustomizableFeedMappings;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmFacets;
+import org.apache.olingo.odata2.api.edm.EdmLiteralKind;
+import org.apache.olingo.odata2.api.edm.EdmSimpleType;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeException;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.client.api.ep.Entity;
+import org.apache.olingo.odata2.client.api.ep.EntitySerializerProperties;
+import org.apache.olingo.odata2.core.ep.EntityProviderProducerException;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityComplexPropertyInfo;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityPropertyInfo;
+import org.apache.olingo.odata2.core.ep.util.FormatXml;
+
+/**
+ * Internal EntityProvider for simple and complex EDM properties which are pre-analyzed as {@link EntityPropertyInfo}.
+ * 
+ */
+public class XmlPropertyEntitySerializer {
+
+  private final boolean validateFacets;
+
+  /**
+   * 
+   * @param writeProperties
+   */
+  public XmlPropertyEntitySerializer(final EntitySerializerProperties writeProperties) {
+    this(writeProperties.isValidatingFacets());
+  }
+
+  /**
+   * 
+   * @param validateFacets
+   */
+  public XmlPropertyEntitySerializer( final boolean validateFacets) {
+    this.validateFacets = validateFacets;
+  }
+
+  /**
+   * Append {@link Object} <code>value</code> based on {@link EntityPropertyInfo} to {@link XMLStreamWriter} in an
+   * already existing XML structure inside the d namespace.
+   * 
+   * @param writer
+   * @param name Name of the outer XML tag
+   * @param propertyInfo
+   * @param value
+   * @throws EntityProviderException
+   */
+  public void append(final XMLStreamWriter writer, final String name, final EntityPropertyInfo propertyInfo,
+      final Object value) throws EntityProviderException {
+    try {
+      writer.writeStartElement(Edm.NAMESPACE_D_2007_08, name);
+
+      if (propertyInfo.isComplex()) {
+        appendProperty(writer, (EntityComplexPropertyInfo) propertyInfo, value);
+      } else {
+        appendProperty(writer, propertyInfo, value);
+      }
+
+      writer.writeEndElement();
+    } catch (XMLStreamException e) {
+      throw new EntityProviderProducerException(EntityProviderException.COMMON, e);
+    } catch (EdmException e) {
+      throw new EntityProviderProducerException(e.getMessageReference(), e);
+    }
+  }
+
+  /**
+   * Serializes custom properties
+   * @param writer
+   * @param name
+   * @param propertyInfo
+   * @param value
+   * @throws EntityProviderException
+   */
+  public void appendCustomProperty(final XMLStreamWriter writer, final String name,
+      final EntityPropertyInfo propertyInfo, final Object value) throws EntityProviderException {
+    try {
+      if (!propertyInfo.isComplex()) {
+        writeStartElementWithCustomNamespace(writer, propertyInfo, name);
+        appendProperty(writer, propertyInfo, value);
+        writer.writeEndElement();
+      }
+    } catch (XMLStreamException e) {
+      throw new EntityProviderProducerException(EntityProviderException.COMMON, e);
+    } catch (EdmException e) {
+      throw new EntityProviderProducerException(e.getMessageReference(), e);
+    }
+  }
+
+  
+  /**
+   * 
+   * @param writer
+   * @param propertyInfo
+   * @param value
+   * @throws XMLStreamException
+   * @throws EdmException
+   * @throws EntityProviderException
+   */
+  private void appendProperty(final XMLStreamWriter writer, final EntityComplexPropertyInfo propertyInfo,
+      final Object value) throws XMLStreamException, EdmException, EntityProviderException {
+
+    if (value == null) {
+      writer.writeAttribute(Edm.NAMESPACE_M_2007_08, FormatXml.ATOM_NULL, FormatXml.ATOM_VALUE_TRUE);
+    } else {
+      writer.writeAttribute(Edm.NAMESPACE_M_2007_08, FormatXml.ATOM_TYPE, getFqnTypeName(propertyInfo));
+      List<EntityPropertyInfo> propertyInfos = propertyInfo.getPropertyInfos();
+      for (EntityPropertyInfo childPropertyInfo : propertyInfos) {
+        if ( value instanceof Map && !((Map<?,?>)value).containsKey(childPropertyInfo.getName())||
+            (value instanceof Entity && (((Entity)value).getProperty(childPropertyInfo.getName()))==null)) {
+          continue;
+        }
+        Object childValue = extractChildValue(value, childPropertyInfo.getName());
+        append(writer, childPropertyInfo.getName(), childPropertyInfo, childValue);
+      }
+    }
+  }
+
+  /**
+   * Returns full qualified name of a type of a given PropertyInfo.
+   * @return Full qualified name
+   */
+  private String getFqnTypeName(final EntityComplexPropertyInfo propertyInfo) throws EdmException {
+    return propertyInfo.getType().getNamespace() + Edm.DELIMITER + propertyInfo.getType().getName();
+  }
+
+  /**
+   * If <code>value</code> is a {@link Map} the element with given <code>name</code> as key is returned.
+   * If <code>value</code> is NOT a {@link Map} its {@link String#valueOf(Object)} result is returned.
+   * 
+   * @param value
+   * @param name
+   * @return name or result (see above)
+   */
+  private Object extractChildValue(final Object value, final String name) {
+    if (value instanceof Map) {
+      Map<?, ?> map = (Map<?, ?>) value;
+      return map.get(name);
+    }else if (value instanceof Entity) {
+      Map<?, ?> map = ((Entity) value).getProperties();
+      return map.get(name);
+    }
+    return String.valueOf(value);
+  }
+
+  /**
+   * Appends a simple-property value to the XML stream.
+   * @param writer the XML stream writer
+   * @param prop property informations
+   * @param value the value of the property
+   * @throws XMLStreamException
+   * @throws EdmException
+   * @throws EntityProviderProducerException 
+   */
+  private void appendProperty(final XMLStreamWriter writer, final EntityPropertyInfo prop, final Object value)
+      throws XMLStreamException, EdmException, EntityProviderProducerException {
+    Object contentValue = value;
+    String mimeType = null;
+    if (prop.getMimeType() != null) {
+      mimeType = prop.getMimeType();
+    } else if (prop.getMapping() != null && prop.getMapping().getMediaResourceMimeTypeKey() != null) {
+      mimeType = (String) extractChildValue(value, prop.getMapping().getMediaResourceMimeTypeKey());
+      contentValue = extractChildValue(value, prop.getName());
+    }
+
+    if (mimeType != null) {
+      writer.writeAttribute(Edm.NAMESPACE_M_2007_08, FormatXml.M_MIME_TYPE, mimeType);
+    }
+
+    final EdmSimpleType type = (EdmSimpleType) prop.getType();
+    final EdmFacets facets = validateFacets ? prop.getFacets() : null;
+    String valueAsString = null;
+    try {
+      valueAsString = type.valueToString(contentValue, EdmLiteralKind.DEFAULT, facets);
+    } catch (EdmSimpleTypeException e) {
+        throw new EntityProviderProducerException(EdmSimpleTypeException.getMessageReference(
+            e.getMessageReference()).updateContent(
+                e.getMessageReference().getContent(), prop.getName()), e);
+    }
+    if (valueAsString == null) {
+      writer.writeAttribute(Edm.NAMESPACE_M_2007_08, FormatXml.ATOM_NULL, FormatXml.ATOM_VALUE_TRUE);
+    } else {
+      writer.writeCharacters(valueAsString);
+    }
+  }
+
+  /**
+   * 
+   * @param writer
+   * @param prop
+   * @param name
+   * @throws XMLStreamException
+   * @throws EntityProviderException
+   */
+  private void writeStartElementWithCustomNamespace(final XMLStreamWriter writer, final EntityPropertyInfo prop,
+      final String name) throws XMLStreamException, EntityProviderException {
+    EdmCustomizableFeedMappings mapping = prop.getCustomMapping();
+    String nsPrefix = mapping.getFcNsPrefix();
+    String nsUri = mapping.getFcNsUri();
+    if (nsUri == null || nsPrefix == null) {
+      throw new EntityProviderProducerException(EntityProviderException.INVALID_NAMESPACE.addContent(name));
+    }
+    writer.writeStartElement(nsPrefix, name, nsUri);
+    writer.writeNamespace(nsPrefix, nsUri);
+  }
+}


[21/24] olingo-odata2 git commit: [OLINGO-1253]Client Module for Olingo v2

Posted by ar...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/JsonSerializerDeserializer.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/JsonSerializerDeserializer.java b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/JsonSerializerDeserializer.java
new file mode 100644
index 0000000..aaba634
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/JsonSerializerDeserializer.java
@@ -0,0 +1,169 @@
+/*******************************************************************************
+ * 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.client.core.ep;
+
+import java.io.BufferedWriter;
+import java.io.InputStream;
+import java.io.OutputStreamWriter;
+import java.util.List;
+
+import org.apache.olingo.odata2.api.batch.BatchException;
+import org.apache.olingo.odata2.api.batch.BatchResponsePart;
+import org.apache.olingo.odata2.api.client.batch.BatchPart;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmFunctionImport;
+import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
+import org.apache.olingo.odata2.api.edm.EdmTypeKind;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.ep.entry.ODataEntry;
+import org.apache.olingo.odata2.api.ep.feed.ODataFeed;
+import org.apache.olingo.odata2.api.processor.ODataErrorContext;
+import org.apache.olingo.odata2.api.processor.ODataResponse;
+import org.apache.olingo.odata2.client.api.ep.ContentTypeBasedDeserializer;
+import org.apache.olingo.odata2.client.api.ep.ContentTypeBasedSerializer;
+import org.apache.olingo.odata2.client.api.ep.Entity;
+import org.apache.olingo.odata2.client.api.ep.EntityCollection;
+import org.apache.olingo.odata2.client.api.ep.EntityCollectionSerializerProperties;
+import org.apache.olingo.odata2.client.api.ep.EntitySerializerProperties;
+import org.apache.olingo.odata2.client.api.ep.EntityStream;
+import org.apache.olingo.odata2.client.core.ep.deserializer.JsonEntityDeserializer;
+import org.apache.olingo.odata2.client.core.ep.serializer.JsonEntryEntitySerializer;
+import org.apache.olingo.odata2.client.core.ep.serializer.JsonFeedEntitySerializer;
+import org.apache.olingo.odata2.core.batch.BatchRequestWriter;
+import org.apache.olingo.odata2.core.batch.BatchResponseWriter;
+import org.apache.olingo.odata2.core.ep.EntityProviderProducerException;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityInfoAggregator;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityPropertyInfo;
+import org.apache.olingo.odata2.core.ep.consumer.JsonErrorDocumentConsumer;
+import org.apache.olingo.odata2.core.ep.util.CircleStreamBuffer;
+
+/**
+ *  This class includes methods to serialize deserialize JSON Content type
+ */
+public class JsonSerializerDeserializer implements ContentTypeBasedSerializer, ContentTypeBasedDeserializer {
+
+  private static final String DEFAULT_CHARSET = "UTF-8";
+
+  @Override
+  public ODataResponse writeEntry(EdmEntitySet entitySet, Entity data) 
+      throws EntityProviderException {
+
+    final EntitySerializerProperties properties = data == null ? 
+        EntitySerializerProperties.serviceRoot(null).build() : data.getWriteProperties() == null ? 
+            EntitySerializerProperties.serviceRoot(null).build() : data.getWriteProperties();
+    final EntityInfoAggregator entityInfo = EntityInfoAggregator.create(entitySet, null);
+    CircleStreamBuffer buffer = new CircleStreamBuffer();
+
+    try {
+      BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(buffer.getOutputStream(), DEFAULT_CHARSET));
+      JsonEntryEntitySerializer producer = new JsonEntryEntitySerializer(properties);
+      producer.append(writer, entityInfo, data);
+      writer.flush();
+      buffer.closeWrite();
+
+      return ODataResponse.entity(buffer.getInputStream())
+          .idLiteral(producer.getLocation())
+          .build();
+    } catch (EntityProviderException e) {
+      buffer.close();
+      throw e;
+    } catch (Exception e) {
+      buffer.close();
+      throw new EntityProviderProducerException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass()
+          .getSimpleName()), e);
+    }
+  
+  }
+
+  @Override
+  public ODataFeed readFeed(EdmEntitySet entitySet, EntityStream content) 
+      throws EntityProviderException {
+    return new JsonEntityDeserializer().readFeed(entitySet, content);
+  }
+
+  @Override
+  public ODataEntry readEntry(EdmEntitySet entitySet, EntityStream content) 
+      throws EntityProviderException {
+    return new JsonEntityDeserializer().readEntry(entitySet, content);
+  
+  }
+
+  @Override
+  public ODataErrorContext readErrorDocument(InputStream errorDocument) throws EntityProviderException {
+    return new JsonErrorDocumentConsumer().readError(errorDocument);
+  }
+
+  @Override
+  public ODataResponse writeFeed(EdmEntitySet entitySet, EntityCollection data) throws EntityProviderException {
+    final EntityCollectionSerializerProperties properties = data == null ? 
+        EntityCollectionSerializerProperties.serviceRoot(null).build() : data.getCollectionProperties() == null ? 
+            EntityCollectionSerializerProperties.serviceRoot(null).build() : data.getCollectionProperties();
+    final EntityInfoAggregator entityInfo = EntityInfoAggregator.create(entitySet, null);
+    CircleStreamBuffer buffer = new CircleStreamBuffer();
+
+    try {
+      BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(buffer.getOutputStream(), DEFAULT_CHARSET));
+      new JsonFeedEntitySerializer(properties).appendAsObject(writer, entityInfo, data);
+      writer.flush();
+      buffer.closeWrite();
+
+      return ODataResponse.entity(buffer.getInputStream()).build();
+    } catch (EntityProviderException e) {
+      buffer.close();
+      throw e;
+    } catch (Exception e) {
+      buffer.close();
+      throw new EntityProviderProducerException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass()
+          .getSimpleName()), e);
+    }
+  }
+
+  @Override
+  public ODataResponse writeBatchResponse(List<BatchResponsePart> batchResponseParts) throws BatchException {
+    BatchResponseWriter batchWriter = new BatchResponseWriter();
+    return batchWriter.writeResponse(batchResponseParts);
+  }
+
+  @Override
+  public InputStream readBatchRequest(List<BatchPart> batchParts,
+      String boundary) {
+    BatchRequestWriter batchWriter = new BatchRequestWriter();
+    return batchWriter.writeBatchRequest(batchParts, boundary);
+  }
+
+  @Override
+  public Object readFunctionImport(EdmFunctionImport functionImport, EntityStream content)
+      throws EntityProviderException {
+    try {
+      if (functionImport.getReturnType().getType().getKind() == EdmTypeKind.ENTITY) {
+        return functionImport.getReturnType().getMultiplicity() == EdmMultiplicity.MANY
+            ? new JsonEntityDeserializer().readFeed(functionImport.getEntitySet(), content)
+            : new JsonEntityDeserializer().readEntry(functionImport.getEntitySet(), content);
+      } else {
+        final EntityPropertyInfo info = EntityInfoAggregator.create(functionImport);
+        return functionImport.getReturnType().getMultiplicity() == EdmMultiplicity.MANY ?
+            new JsonEntityDeserializer().readCollection(info, content) :
+            new JsonEntityDeserializer().readProperty(info, content).get(info.getName());
+      }
+    } catch (final EdmException e) {
+      throw new EntityProviderException(e.getMessageReference(), e);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/JsonEntityDeserializer.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/JsonEntityDeserializer.java b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/JsonEntityDeserializer.java
new file mode 100644
index 0000000..49c61d7
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/JsonEntityDeserializer.java
@@ -0,0 +1,218 @@
+/*******************************************************************************
+ * 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.client.core.ep.deserializer;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.UnsupportedEncodingException;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.ep.entry.ODataEntry;
+import org.apache.olingo.odata2.api.ep.feed.ODataDeltaFeed;
+import org.apache.olingo.odata2.api.ep.feed.ODataFeed;
+import org.apache.olingo.odata2.client.api.ep.EntityStream;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityInfoAggregator;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityPropertyInfo;
+
+import com.google.gson.stream.JsonReader;
+
+/**
+ *  This class includes method for deserialization of feed and entry data
+ */
+public class JsonEntityDeserializer {
+
+  /** Default used charset for reader */
+  private static final String DEFAULT_CHARSET = "UTF-8";
+
+  /**
+   * Returns an ODataEntry deserializing EntityStream
+   * @param entitySet
+   * @param entityStream
+   * @return ODataEntry
+   * @throws EntityProviderException
+   */
+  public ODataEntry readEntry(final EdmEntitySet entitySet, final EntityStream entityStream) 
+      throws EntityProviderException {
+    JsonReader reader = null;
+    EntityProviderException cachedException = null;
+
+    try {
+      EntityInfoAggregator eia = EntityInfoAggregator.create(entitySet);
+      reader = createJsonReader(entityStream.getContent());
+
+      return new JsonEntryDeserializer(reader, eia, entityStream.getReadProperties()).readSingleEntry();
+    } catch (UnsupportedEncodingException e) {
+      cachedException =
+          new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass()
+              .getSimpleName()), e);
+      throw cachedException;
+    } finally {// NOPMD (suppress DoNotThrowExceptionInFinally)
+      if (reader != null) {
+        try {
+          reader.close();
+        } catch (IOException e) { //NOPMD  - suppressed
+          if (cachedException != null) { //NOSONAR
+            throw cachedException; //NOSONAR
+          } else {
+            throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.//NOSONAR
+                addContent(e.getClass()
+                .getSimpleName()), e); 
+          }
+        }
+      }
+    }
+  }
+
+  /**
+   * Returns an ODataFeed deserializing EntityStream
+   * @param entitySet
+   * @param entityStream
+   * @return ODataFeed
+   * @throws EntityProviderException
+   */
+  public ODataFeed readFeed(final EdmEntitySet entitySet, final EntityStream entityStream) 
+      throws EntityProviderException {
+    return readDeltaFeed(entitySet, entityStream);
+  }
+
+  /**
+   * Returns an ODataDeltaFeed deserializing EntityStream
+   * @param entitySet
+   * @param entityStream
+   * @return ODataDeltaFeed
+   * @throws EntityProviderException
+   */
+  public ODataDeltaFeed readDeltaFeed(final EdmEntitySet entitySet, final EntityStream entityStream) 
+      throws EntityProviderException {
+
+    JsonReader reader = null;
+    EntityProviderException cachedException = null;
+
+    try {
+      EntityInfoAggregator eia = EntityInfoAggregator.create(entitySet);
+      reader = createJsonReader(entityStream.getContent());
+
+      JsonFeedDeserializer jfc = new JsonFeedDeserializer(reader, eia, entityStream.getReadProperties());
+      return jfc.readFeedStandalone();
+    } catch (UnsupportedEncodingException e) {
+      cachedException =
+          new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass()
+              .getSimpleName()), e);
+      throw cachedException;
+    } finally {// NOPMD (suppress DoNotThrowExceptionInFinally)
+      if (reader != null) {
+        try {
+          reader.close();
+        } catch (IOException e) { //NOPMD  - suppressed
+          if (cachedException != null) { //NOSONAR
+            throw cachedException; //NOSONAR
+          } else {
+            throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.//NOSONAR
+                addContent(e.getClass()
+                .getSimpleName()), e); 
+          }
+        }
+      }
+    }
+  }
+
+/**
+ * 
+ * @param content
+ * @return JsonReader
+ * @throws EntityProviderException
+ * @throws UnsupportedEncodingException
+ */
+  private JsonReader createJsonReader(final Object content) throws EntityProviderException,
+      UnsupportedEncodingException {
+
+    if (content == null) {
+      throw new EntityProviderException(EntityProviderException.ILLEGAL_ARGUMENT
+          .addContent("Got not supported NULL object as content to de-serialize."));
+    }
+
+    if (content instanceof InputStream) {
+      return new JsonReader(new InputStreamReader((InputStream) content, DEFAULT_CHARSET));
+    }
+    throw new EntityProviderException(EntityProviderException.ILLEGAL_ARGUMENT
+        .addContent("Found not supported content of class '" + content.getClass() + "' to de-serialize."));
+  }
+  
+  public List<?> readCollection(final EntityPropertyInfo info, final EntityStream entityStream) 
+      throws EntityProviderException {
+    JsonReader reader = null;
+    EntityProviderException cachedException = null;
+
+    try {
+      reader = createJsonReader(entityStream.getContent());
+      return new JsonPropertyDeserializer().readCollection(reader, info, entityStream.getReadProperties());
+    } catch (final UnsupportedEncodingException e) {
+      cachedException = new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED
+          .addContent(e.getClass().getSimpleName()), e);
+      throw cachedException;
+    } finally {// NOPMD (suppress DoNotThrowExceptionInFinally)
+      if (reader != null) {
+        try {
+          reader.close();
+        } catch (final IOException e) {
+          if (cachedException != null) {
+            throw cachedException;
+          } else {
+            throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED
+                .addContent(e.getClass().getSimpleName()), e);
+          }
+        }
+      }
+    }
+  }
+  
+  public Map<String, Object> readProperty(final EntityPropertyInfo propertyInfo, final EntityStream entityStream) 
+      throws EntityProviderException {
+    JsonReader reader = null;
+    EntityProviderException cachedException = null;
+
+    try {
+      reader = createJsonReader(entityStream.getContent());
+      return new JsonPropertyDeserializer().readPropertyStandalone(reader, propertyInfo, 
+          entityStream.getReadProperties());
+    } catch (final UnsupportedEncodingException e) {
+      cachedException =
+          new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass()
+              .getSimpleName()), e);
+      throw cachedException;
+    } finally {// NOPMD (suppress DoNotThrowExceptionInFinally)
+      if (reader != null) {
+        try {
+          reader.close();
+        } catch (final IOException e) {
+          if (cachedException != null) {
+            throw cachedException;
+          } else {
+            throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass()
+                .getSimpleName()), e);
+          }
+        }
+      }
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/JsonEntryDeserializer.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/JsonEntryDeserializer.java b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/JsonEntryDeserializer.java
new file mode 100644
index 0000000..f9fb915
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/JsonEntryDeserializer.java
@@ -0,0 +1,451 @@
+/*******************************************************************************
+ * 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.client.core.ep.deserializer;
+
+import java.io.IOException;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmLiteralKind;
+import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
+import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeException;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.ep.entry.ODataEntry;
+import org.apache.olingo.odata2.api.ep.feed.ODataFeed;
+import org.apache.olingo.odata2.api.exception.ODataApplicationException;
+import org.apache.olingo.odata2.client.api.ep.DeserializerProperties;
+import org.apache.olingo.odata2.client.api.ep.callback.OnDeserializeInlineContent;
+import org.apache.olingo.odata2.core.edm.EdmDateTimeOffset;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityInfoAggregator;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityPropertyInfo;
+import org.apache.olingo.odata2.core.ep.aggregator.NavigationPropertyInfo;
+import org.apache.olingo.odata2.core.ep.entry.DeletedEntryMetadataImpl;
+import org.apache.olingo.odata2.core.ep.entry.EntryMetadataImpl;
+import org.apache.olingo.odata2.core.ep.entry.MediaMetadataImpl;
+import org.apache.olingo.odata2.core.ep.entry.ODataEntryImpl;
+import org.apache.olingo.odata2.core.ep.feed.JsonFeedEntry;
+import org.apache.olingo.odata2.core.ep.util.FormatJson;
+
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonToken;
+
+/**
+ *  This class Deserializes JsonEntry payloads
+ */
+public class JsonEntryDeserializer {
+
+  private final EntityInfoAggregator eia;
+  private final JsonReader reader;
+  private final DeserializerProperties readProperties;
+
+  private ODataEntryImpl resultEntry;
+  private Map<String, Object> properties;
+  private MediaMetadataImpl mediaMetadata;
+  private EntryMetadataImpl entryMetadata;
+
+  private DeletedEntryMetadataImpl resultDeletedEntry;
+
+  /**
+   * 
+   * @param reader
+   * @param eia
+   * @param readProperties
+   */
+  public JsonEntryDeserializer(final JsonReader reader, final EntityInfoAggregator eia,
+      final DeserializerProperties readProperties) {
+    this.eia = eia;
+    this.readProperties = readProperties;
+    this.reader = reader;
+  }
+
+  /**
+   * Returns ODataEntry deserializing a single entry
+   * @return ODataEntry
+   * @throws EntityProviderException
+   */
+  public ODataEntry readSingleEntry() throws EntityProviderException {
+    try {
+      reader.beginObject();
+      String nextName = reader.nextName();
+      if (FormatJson.D.equals(nextName)) {
+        reader.beginObject();
+        readEntryContent();
+        reader.endObject();
+      } else {
+        handleName(nextName);
+        readEntryContent();
+      }
+      reader.endObject();
+
+      if (reader.peek() != JsonToken.END_DOCUMENT) {
+        throw new EntityProviderException(EntityProviderException.END_DOCUMENT_EXPECTED.addContent(reader.peek()
+            .toString()));
+      }
+    } catch (IOException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass()
+          .getSimpleName()), e);
+    } catch (EdmException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass()
+          .getSimpleName()), e);
+    } catch (IllegalStateException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass()
+          .getSimpleName()), e);
+    }
+
+    return resultEntry;
+  }
+
+  /**
+   * Returns Feed deserializing feed entry
+   * @return JsonFeedEntry
+   * @throws EdmException
+   * @throws EntityProviderException
+   * @throws IOException
+   */
+  public JsonFeedEntry readFeedEntry() throws EdmException, EntityProviderException, IOException {//NOSONAR
+    reader.beginObject();
+    readEntryContent();
+    reader.endObject();
+
+    if (resultDeletedEntry == null) {
+      return new JsonFeedEntry(resultEntry);
+    } else {
+      return new JsonFeedEntry(resultDeletedEntry);
+    }
+  }
+
+  /**
+   * 
+   * @throws IOException
+   * @throws EdmException
+   * @throws EntityProviderException
+   */
+  private void readEntryContent() throws IOException, EdmException, EntityProviderException {
+    while (reader.hasNext()) {
+      final String name = reader.nextName();
+      handleName(name);
+    }
+  }
+
+  /**
+   * Ensure that instance field {@link #resultEntry} exists.
+   * If it not already exists create an instance (as well as all other necessary objects like: {@link #properties},
+   * {@link #mediaMetadata}, {@link #entryMetadata}, {@link #expandSelectTree}).
+   */
+  private void ensureODataEntryExists() {
+    if (resultEntry == null) {
+      properties = new HashMap<String, Object>();
+      mediaMetadata = new MediaMetadataImpl();
+      entryMetadata = new EntryMetadataImpl();
+      
+      resultEntry = new ODataEntryImpl(properties, mediaMetadata, entryMetadata, null);
+    }
+  }
+
+  /**
+   * Ensure that instance field {@link #resultDeletedEntry} exists.
+   * If it not already exists create an instance.
+   */
+  private void ensureDeletedEntryMetadataExists() {
+    if (resultDeletedEntry == null) {
+      resultDeletedEntry = new DeletedEntryMetadataImpl();
+    }
+  }
+
+  /**
+   * 
+   * @param name
+   * @throws IOException
+   * @throws EdmException
+   * @throws EntityProviderException
+   */
+  private void handleName(final String name) throws IOException, EdmException, EntityProviderException {
+    if (FormatJson.METADATA.equals(name)) {
+      ensureODataEntryExists();
+      readMetadata();
+      validateMetadata();
+    } else if (FormatJson.ODATA_CONTEXT.equals(name)) {
+      readODataContext();
+    } else {
+      ensureODataEntryExists();
+      EntityPropertyInfo propertyInfo = eia.getPropertyInfo(name);
+      if (propertyInfo != null) {
+        //TODO: put Type mapping instead of null
+        Object propertyValue = new JsonPropertyDeserializer()
+            .readPropertyValue(reader, propertyInfo, null, readProperties);
+        if (properties.containsKey(name)) {
+          throw new EntityProviderException(EntityProviderException.DOUBLE_PROPERTY.addContent(name));
+        }
+        properties.put(name, propertyValue);
+      } else {
+        readNavigationProperty(name);
+      }
+    }
+  }
+  /**
+   * 
+   * @throws IOException
+   * @throws EntityProviderException
+   */
+  private void readODataContext() throws IOException, EntityProviderException {
+    String contextValue = reader.nextString();
+    if (contextValue == null) {
+      throw new EntityProviderException(EntityProviderException.MISSING_ATTRIBUTE.addContent(FormatJson.ODATA_CONTEXT)
+          .addContent(FormatJson.RESULTS));
+    }
+
+    if (contextValue.startsWith(FormatJson.DELTA_CONTEXT_PREFIX)
+        && contextValue.endsWith(FormatJson.DELTA_CONTEXT_POSTFIX)) {
+      while (reader.hasNext()) {
+        ensureDeletedEntryMetadataExists();
+        String name = reader.nextName();
+        String value = reader.nextString();
+        if (FormatJson.ID.equals(name)) {
+          resultDeletedEntry.setUri(value);
+        } else if (FormatJson.DELTA_WHEN.equals(name)) {
+          Date when = parseWhen(value);
+          resultDeletedEntry.setWhen(when);
+        }
+      }
+    }
+  }
+
+  /**
+   * 
+   * @param value
+   * @return Date
+   * @throws EntityProviderException
+   */
+  private Date parseWhen(final String value) throws EntityProviderException {
+    try {
+      return EdmDateTimeOffset.getInstance().valueOfString(value, EdmLiteralKind.JSON, null, Date.class);
+    } catch (EdmSimpleTypeException e) {
+      throw new EntityProviderException(EntityProviderException.INVALID_DELETED_ENTRY_METADATA
+          .addContent("Unparsable format for when field value."), e);
+    }
+  }
+
+  /**
+   * 
+   * @throws IOException
+   * @throws EdmException
+   * @throws EntityProviderException
+   */
+  private void readMetadata() throws IOException, EdmException, EntityProviderException {//NOSONAR
+    String name = null;
+    String value = null;
+    reader.beginObject();
+    while (reader.hasNext()) {
+      name = reader.nextName();
+
+      if (FormatJson.PROPERTIES.equals(name)) {
+        reader.skipValue();
+        continue;
+      }
+
+      value = reader.nextString();
+      if (FormatJson.ID.equals(name)) {
+        entryMetadata.setId(value);
+      } else if (FormatJson.URI.equals(name)) {
+        entryMetadata.setUri(value);
+      } else if (FormatJson.TYPE.equals(name)) {
+        String fullQualifiedName = eia.getEntityType().getNamespace() + Edm.DELIMITER + eia.getEntityType().getName();
+        if (!fullQualifiedName.equals(value)) {
+          throw new EntityProviderException(EntityProviderException.INVALID_ENTITYTYPE.addContent(fullQualifiedName)
+              .addContent(value));
+        }
+      } else if (FormatJson.ETAG.equals(name)) {
+        entryMetadata.setEtag(value);
+      } else if (FormatJson.EDIT_MEDIA.equals(name)) {
+        mediaMetadata.setEditLink(value);
+      } else if (FormatJson.MEDIA_SRC.equals(name)) {
+        mediaMetadata.setSourceLink(value);
+      } else if (FormatJson.MEDIA_ETAG.equals(name)) {
+        mediaMetadata.setEtag(value);
+      } else if (FormatJson.CONTENT_TYPE.equals(name)) {
+        mediaMetadata.setContentType(value);
+      } else {
+        throw new EntityProviderException(EntityProviderException.INVALID_CONTENT.addContent(name).addContent(
+            FormatJson.METADATA));
+      }
+    }
+
+    reader.endObject();
+  }
+
+  /**
+   * 
+   * @throws EdmException
+   * @throws EntityProviderException
+   */
+  private void validateMetadata() throws EdmException, EntityProviderException {
+    if (eia.getEntityType().hasStream()) {
+      if (mediaMetadata.getSourceLink() == null) {
+        throw new EntityProviderException(EntityProviderException.MISSING_ATTRIBUTE.addContent(FormatJson.MEDIA_SRC)
+            .addContent(FormatJson.METADATA));
+      }
+      if (mediaMetadata.getContentType() == null) {
+        throw new EntityProviderException(EntityProviderException.MISSING_ATTRIBUTE.addContent(FormatJson.CONTENT_TYPE)
+            .addContent(FormatJson.METADATA));
+      }
+    } else {
+      if (mediaMetadata.getContentType() != null || mediaMetadata.getEditLink() != null
+          || mediaMetadata.getEtag() != null || mediaMetadata.getSourceLink() != null) {
+        throw new EntityProviderException(EntityProviderException.MEDIA_DATA_NOT_INITIAL);
+      }
+    }
+  }
+
+  /**
+   * 
+   * @param navigationPropertyName
+   * @throws IOException
+   * @throws EntityProviderException
+   * @throws EdmException
+   */
+  private void readNavigationProperty(final String navigationPropertyName) throws IOException, EntityProviderException,
+      EdmException {
+    NavigationPropertyInfo navigationPropertyInfo = eia.getNavigationPropertyInfo(navigationPropertyName);
+    if (navigationPropertyInfo == null) {
+      throw new EntityProviderException(EntityProviderException.ILLEGAL_ARGUMENT.addContent(navigationPropertyName));
+    }
+
+    JsonToken peek = reader.peek();
+    if (peek == JsonToken.BEGIN_OBJECT) {
+      reader.beginObject();
+      String name = reader.nextName();
+      if (FormatJson.DEFERRED.equals(name)) {
+        reader.beginObject();
+        String uri = reader.nextName();
+        if (FormatJson.URI.equals(uri)) {
+          String value = reader.nextString(); 
+          entryMetadata.putAssociationUri(navigationPropertyInfo.getName(), value);
+        } else {
+          throw new EntityProviderException(EntityProviderException.ILLEGAL_ARGUMENT.addContent(uri));
+        }
+        reader.endObject();
+      } else {
+        handleInlineEntries(navigationPropertyName, name);
+      }
+      reader.endObject();
+    } else if (peek == JsonToken.NULL) {
+      reader.nextNull();
+    } else {
+      handleArray(navigationPropertyName);
+    }
+   }
+
+  /**
+   * @param navigationPropertyName
+   * @throws EdmException
+   * @throws EntityProviderException
+   * @throws IOException
+   */
+  private void handleArray(final String navigationPropertyName) throws EdmException, EntityProviderException,
+      IOException {
+    final EdmNavigationProperty navigationProperty =
+        (EdmNavigationProperty) eia.getEntityType().getProperty(navigationPropertyName);
+    final EdmEntitySet inlineEntitySet = eia.getEntitySet().getRelatedEntitySet(navigationProperty);
+    final EntityInfoAggregator inlineInfo = EntityInfoAggregator.create(inlineEntitySet);
+    OnDeserializeInlineContent callback = readProperties.getCallback();
+    DeserializerProperties inlineReadProperties;
+    try {
+      if (callback == null) {
+        inlineReadProperties =
+            DeserializerProperties.init()
+                .isValidatingFacets(readProperties.isValidatingFacets())
+                .build();
+
+      } else {
+        inlineReadProperties = callback.receiveReadProperties(readProperties, navigationProperty);
+      }
+    } catch (ODataApplicationException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass()
+          .getSimpleName()), e);
+    }
+    
+    ODataFeed feed = new JsonFeedDeserializer(reader, inlineInfo, inlineReadProperties).readInlineFeedStandalone();
+    properties.put(navigationPropertyName, feed);
+    resultEntry.setContainsInlineEntry(true);
+  }
+
+  /**
+   * @param navigationPropertyName
+   * @param name
+   * @throws EdmException
+   * @throws EntityProviderException
+   * @throws IOException
+   */
+  private void handleInlineEntries(final String navigationPropertyName, String name) throws EdmException,
+      EntityProviderException, IOException {
+    EdmNavigationProperty navigationProperty =
+        (EdmNavigationProperty) eia.getEntityType().getProperty(navigationPropertyName);
+    EdmEntitySet inlineEntitySet = eia.getEntitySet().getRelatedEntitySet(navigationProperty);
+    EntityInfoAggregator inlineEia = EntityInfoAggregator.create(inlineEntitySet);
+    OnDeserializeInlineContent callback = readProperties.getCallback();
+    final DeserializerProperties inlineReadProperties;
+    try {
+      if (callback == null) {
+        inlineReadProperties =
+            DeserializerProperties.init()
+                .isValidatingFacets(readProperties.isValidatingFacets())
+                .build();
+
+      } else {
+        inlineReadProperties = callback.receiveReadProperties(readProperties, navigationProperty);
+      }
+    } catch (ODataApplicationException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass()
+          .getSimpleName()), e);
+    }
+    if (navigationProperty.getMultiplicity() == EdmMultiplicity.MANY) {
+      JsonFeedDeserializer inlineConsumer = new JsonFeedDeserializer(reader, inlineEia, inlineReadProperties);
+      ODataFeed feed = inlineConsumer.readStartedInlineFeed(name);
+      properties.put(navigationPropertyName, feed);
+      resultEntry.setContainsInlineEntry(true);
+    } else {
+      JsonEntryDeserializer inlineConsumer = new JsonEntryDeserializer(reader, inlineEia, inlineReadProperties);
+      ODataEntry entry = inlineConsumer.readInlineEntry(name);
+      properties.put(navigationPropertyName, entry);
+      resultEntry.setContainsInlineEntry(true);
+    }
+  }
+  
+  /**
+   * 
+   * @param name
+   * @return ODataEntry
+   * @throws EdmException
+   * @throws EntityProviderException
+   * @throws IOException
+   */
+  private ODataEntry readInlineEntry(final String name) throws EdmException, EntityProviderException, IOException {
+    // consume the already started content
+    handleName(name);
+    // consume the rest of the entry content
+    readEntryContent();
+    return resultEntry;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/JsonErrorDocumentDeserializer.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/JsonErrorDocumentDeserializer.java b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/JsonErrorDocumentDeserializer.java
new file mode 100644
index 0000000..8b5cc45
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/JsonErrorDocumentDeserializer.java
@@ -0,0 +1,278 @@
+/*******************************************************************************
+ * 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.client.core.ep.deserializer;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.UnsupportedEncodingException;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.processor.ODataErrorContext;
+import org.apache.olingo.odata2.core.commons.ContentType;
+import org.apache.olingo.odata2.core.ep.util.FormatJson;
+
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonToken;
+
+/**
+ * Consuming (read / deserialization) for OData error document in JSON format.
+ */
+public class JsonErrorDocumentDeserializer {
+  /** Default used charset for reader */
+  private static final String DEFAULT_CHARSET = "UTF-8";
+  private static final String FOUND = "' found.";
+  /**
+   * Map containing language code (language - country) to Locale mapping
+   * based on Locale.getAvailableLocales()
+   * */
+  private static final Map<String, Locale> AVAILABLE_LOCALES = new HashMap<String, Locale>();
+  static {
+    Locale[] locales = Locale.getAvailableLocales();
+    for (Locale l : locales) {
+      AVAILABLE_LOCALES.put(l.getLanguage() + "-" + l.getCountry(), l);
+    }
+  }
+
+  /**
+   * Deserialize / read OData error document in ODataErrorContext.
+   * 
+   * @param errorDocument OData error document in JSON format
+   * @return created ODataErrorContext based on input stream content.
+   * @throws EntityProviderException if an exception during read / deserialization occurs.
+   */
+  public ODataErrorContext readError(final InputStream errorDocument) throws EntityProviderException {
+    JsonReader reader = createJsonReader(errorDocument);
+    try {
+      return parseJson(reader);
+    } catch (IOException e) {
+      throw new EntityProviderException(
+          EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getMessage()), e);
+    }
+  }
+
+  /**
+   * 
+   * @param reader
+   * @return ODataErrorContext
+   * @throws IOException
+   * @throws EntityProviderException
+   */
+  private ODataErrorContext parseJson(final JsonReader reader) throws IOException, EntityProviderException {
+    ODataErrorContext errorContext;
+
+    if (reader.hasNext()) {
+      reader.beginObject();
+      String currentName = reader.nextName();
+      if (FormatJson.ERROR.equals(currentName)) {
+        errorContext = parseError(reader);
+      } else {
+        throw new EntityProviderException(EntityProviderException.INVALID_STATE.addContent(
+            "Invalid object with name '" + currentName + FOUND));
+      }
+    } else {
+      throw new EntityProviderException(EntityProviderException.INVALID_STATE.addContent(
+          "No content to parse found."));
+    }
+
+    errorContext.setContentType(ContentType.APPLICATION_JSON.toContentTypeString());
+    return errorContext;
+  }
+
+  /**
+   * 
+   * @param reader
+   * @return ODataErrorContext
+   * @throws IOException
+   * @throws EntityProviderException
+   */
+  private ODataErrorContext parseError(final JsonReader reader) throws IOException, EntityProviderException {
+    ODataErrorContext errorContext = new ODataErrorContext();
+    String currentName;
+    reader.beginObject();
+    boolean messageFound = false;
+    boolean codeFound = false;
+
+    while (reader.hasNext()) {
+      currentName = reader.nextName();
+      if (FormatJson.CODE.equals(currentName)) {
+        codeFound = true;
+        errorContext.setErrorCode(getValue(reader));
+      } else if (FormatJson.MESSAGE.equals(currentName)) {
+        messageFound = true;
+        parseMessage(reader, errorContext);
+      } else if (FormatJson.INNER_ERROR.equals(currentName)) {
+        parseInnerError(reader, errorContext);
+      } else {
+        throw new EntityProviderException(EntityProviderException.INVALID_STATE.addContent(
+            "Invalid name '" + currentName + FOUND));
+      }
+    }
+
+    if (!codeFound) {
+      throw new EntityProviderException(
+          EntityProviderException.MISSING_PROPERTY.addContent("Mandatory 'code' property not found.'"));
+    }
+    if (!messageFound) {
+      throw new EntityProviderException(
+          EntityProviderException.MISSING_PROPERTY.addContent("Mandatory 'message' property not found.'"));
+    }
+
+    reader.endObject();
+    return errorContext;
+  }
+
+  /**
+   * 
+   * @param reader
+   * @param errorContext
+   * @throws IOException
+   */
+  private void parseInnerError(final JsonReader reader, final ODataErrorContext errorContext) throws IOException {
+    JsonToken token = reader.peek();
+    if (token == JsonToken.STRING) {
+      // implementation for parse content as provided by JsonErrorDocumentProducer
+      String innerError = reader.nextString();
+      errorContext.setInnerError(innerError);
+    } else if (token == JsonToken.BEGIN_OBJECT) {
+      // implementation for OData v2 Section 2.2.8.1.2 JSON Error Response
+      // (RFC4627 Section 2.2 -> https://www.ietf.org/rfc/rfc4627.txt))
+      // currently partial provided
+      errorContext.setInnerError(readJson(reader));
+    }
+  }
+
+  /**
+   * 
+   * @param reader
+   * @return String
+   * @throws IOException
+   */
+  private String readJson(final JsonReader reader) throws IOException {
+    StringBuilder sb = new StringBuilder();
+
+    while (reader.hasNext()) {
+      JsonToken token = reader.peek();
+      if (token == JsonToken.NAME) {
+        if (sb.length() > 0) {
+          sb.append(",");
+        }
+        String name = reader.nextName();
+        sb.append("\"").append(name).append("\"").append(":");
+      } else if (token == JsonToken.BEGIN_OBJECT) {
+        reader.beginObject();
+        sb.append("{")
+            .append(readJson(reader))
+            .append("}");
+        reader.endObject();
+      } else if (token == JsonToken.BEGIN_ARRAY) {
+        reader.beginArray();
+        sb.append("[")
+            .append(readJson(reader))
+            .append("]");
+        reader.endArray();
+      } else {
+        sb.append("\"")
+            .append(reader.nextString())
+            .append("\"");
+      }
+    }
+
+    return sb.toString();
+  }
+
+  /**
+   * 
+   * @param reader
+   * @param errorContext
+   * @throws IOException
+   * @throws EntityProviderException
+   */
+  private void parseMessage(final JsonReader reader, final ODataErrorContext errorContext)
+      throws IOException, EntityProviderException {
+
+    reader.beginObject();
+    boolean valueFound = false;
+    boolean langFound = false;
+    String currentName;
+
+    while (reader.hasNext()) {
+      currentName = reader.nextName();
+      if (FormatJson.LANG.equals(currentName)) {
+        langFound = true;
+        String langValue = getValue(reader);
+        if (langValue != null) {
+          errorContext.setLocale(getLocale(langValue));
+        }
+      } else if (FormatJson.VALUE.equals(currentName)) {
+        valueFound = true;
+        errorContext.setMessage(getValue(reader));
+      } else {
+        throw new EntityProviderException(EntityProviderException.INVALID_STATE.addContent("Invalid name '" +
+            currentName + FOUND));
+      }
+    }
+
+    if (!langFound) {
+      throw new EntityProviderException(
+          EntityProviderException.MISSING_PROPERTY.addContent("Mandatory 'lang' property not found.'"));
+    }
+    if (!valueFound) {
+      throw new EntityProviderException(
+          EntityProviderException.MISSING_PROPERTY.addContent("Mandatory 'value' property not found.'"));
+    }
+    reader.endObject();
+  }
+
+  private Locale getLocale(final String langValue) {
+    return AVAILABLE_LOCALES.get(langValue);
+  }
+
+  /**
+   * Read the string value from the JsonReader or 'null' if no value is available.
+   * 
+   * @param reader to read from
+   * @return the string value or 'null'
+   * @throws IOException if an exception occurs
+   */
+  private String getValue(final JsonReader reader) throws IOException {
+    JsonToken token = reader.peek();
+    if (JsonToken.NULL == token) {
+      reader.skipValue();
+      return null;
+    }
+    return reader.nextString();
+  }
+
+  private JsonReader createJsonReader(final InputStream in) throws EntityProviderException {
+    if (in == null) {
+      throw new EntityProviderException(EntityProviderException.INVALID_STATE
+          .addContent(("Got not supported NULL object as content to de-serialize.")));
+    }
+    try {
+      return new JsonReader(new InputStreamReader(in, DEFAULT_CHARSET));
+    } catch (final UnsupportedEncodingException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass()
+          .getSimpleName()), e);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/JsonFeedDeserializer.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/JsonFeedDeserializer.java b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/JsonFeedDeserializer.java
new file mode 100644
index 0000000..dd79c3a
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/JsonFeedDeserializer.java
@@ -0,0 +1,255 @@
+/*******************************************************************************
+ * 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.client.core.ep.deserializer;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.ep.entry.DeletedEntryMetadata;
+import org.apache.olingo.odata2.api.ep.entry.ODataEntry;
+import org.apache.olingo.odata2.api.ep.feed.ODataDeltaFeed;
+import org.apache.olingo.odata2.api.ep.feed.ODataFeed;
+import org.apache.olingo.odata2.client.api.ep.DeserializerProperties;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityInfoAggregator;
+import org.apache.olingo.odata2.core.ep.feed.FeedMetadataImpl;
+import org.apache.olingo.odata2.core.ep.feed.JsonFeedEntry;
+import org.apache.olingo.odata2.core.ep.feed.ODataDeltaFeedImpl;
+import org.apache.olingo.odata2.core.ep.util.FormatJson;
+
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonToken;
+
+/**
+ *  This class Deserializes JsonFeed payloads
+ */
+public class JsonFeedDeserializer {
+
+  private JsonReader reader;
+  private EntityInfoAggregator eia;
+  private DeserializerProperties readProperties;
+  private List<DeletedEntryMetadata> deletedEntries = new ArrayList<DeletedEntryMetadata>();
+  private List<ODataEntry> entries = new ArrayList<ODataEntry>();
+  private FeedMetadataImpl feedMetadata = new FeedMetadataImpl();
+  private boolean resultsArrayPresent = false;
+  private static final String JSONFEED = "JsonFeed";
+
+  /**
+   * 
+   * @param reader
+   * @param eia
+   * @param readProperties
+   */
+  public JsonFeedDeserializer(final JsonReader reader, final EntityInfoAggregator eia,
+      final DeserializerProperties readProperties) {
+    this.reader = reader;
+    this.eia = eia;
+    this.readProperties = readProperties;
+  }
+
+  /**
+   * 
+   * @return ODataDeltaFeed
+   * @throws EntityProviderException
+   */
+  public ODataDeltaFeed readFeedStandalone() throws EntityProviderException {
+    try {
+      readFeed();
+
+      if (reader.peek() != JsonToken.END_DOCUMENT) {
+
+        throw new EntityProviderException(EntityProviderException.END_DOCUMENT_EXPECTED.addContent(reader.peek()
+            .toString()));
+      }
+
+    } catch (IOException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass()
+          .getSimpleName()), e);
+    } catch (EdmException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass()
+          .getSimpleName()), e);
+    } catch (IllegalStateException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass()
+          .getSimpleName()), e);
+    }
+    return new ODataDeltaFeedImpl(entries, feedMetadata, deletedEntries);
+  }
+
+  /**
+   * 
+   * @throws IOException
+   * @throws EdmException
+   * @throws EntityProviderException
+   */
+  private void readFeed() throws IOException, EdmException, EntityProviderException {
+    JsonToken peek = reader.peek();
+    if (peek == JsonToken.BEGIN_ARRAY) {
+      readArrayContent();
+    } else {
+      reader.beginObject();
+      final String nextName = reader.nextName();
+      if (FormatJson.D.equals(nextName)) {
+        if (reader.peek() == JsonToken.BEGIN_ARRAY) {
+          readArrayContent();
+        } else {
+          reader.beginObject();
+          readFeedContent();
+          reader.endObject();
+        }
+      } else {
+        handleName(nextName);
+        readFeedContent();
+      }
+
+      reader.endObject();
+    }
+  }
+
+  /**
+   * 
+   * @throws IOException
+   * @throws EdmException
+   * @throws EntityProviderException
+   */
+  private void readFeedContent() throws IOException, EdmException, EntityProviderException {
+    while (reader.hasNext()) {
+      final String nextName = reader.nextName();
+      handleName(nextName);
+    }
+
+    if (!resultsArrayPresent) {
+      throw new EntityProviderException(EntityProviderException.MISSING_RESULTS_ARRAY);
+    }
+  }
+
+  /**
+   * 
+   * @param nextName
+   * @throws IOException
+   * @throws EdmException
+   * @throws EntityProviderException
+   */
+  private void handleName(final String nextName) throws IOException, EdmException, EntityProviderException {
+    if (FormatJson.RESULTS.equals(nextName)) {
+      resultsArrayPresent = true;
+      readArrayContent();
+
+    } else if (FormatJson.COUNT.equals(nextName)) {
+      readInlineCount(reader, feedMetadata);
+
+    } else if (FormatJson.NEXT.equals(nextName)) {
+      if (reader.peek() == JsonToken.STRING && feedMetadata.getNextLink() == null) {
+        String nextLink = reader.nextString();
+        feedMetadata.setNextLink(nextLink);
+      } else {
+        throw new EntityProviderException(EntityProviderException.INVALID_CONTENT.addContent(nextName).addContent(
+            JSONFEED));
+      }
+
+    } else if (FormatJson.DELTA.equals(nextName)) {
+      if (reader.peek() == JsonToken.STRING && feedMetadata.getDeltaLink() == null) {
+        String deltaLink = reader.nextString();
+        feedMetadata.setDeltaLink(deltaLink);
+      } else {
+        throw new EntityProviderException(EntityProviderException.INVALID_CONTENT.addContent(nextName).addContent(
+            JSONFEED));
+      }
+    } else {
+      throw new EntityProviderException(EntityProviderException.INVALID_CONTENT.addContent(nextName).addContent(
+          JSONFEED));
+    }
+  }
+
+  /**
+   * 
+   * @throws IOException
+   * @throws EdmException
+   * @throws EntityProviderException
+   */
+  private void readArrayContent() throws IOException, EdmException, EntityProviderException {
+    reader.beginArray();
+    while (reader.hasNext()) {
+      final JsonFeedEntry entry = new JsonEntryDeserializer(reader, eia, readProperties).readFeedEntry();
+      if (entry.isODataEntry()) {
+        entries.add(entry.getODataEntry());
+      } else {
+        deletedEntries.add(entry.getDeletedEntryMetadata());
+      }
+    }
+    reader.endArray();
+  }
+
+  /**
+   * 
+   * @param reader
+   * @param feedMetadata
+   * @throws IOException
+   * @throws EntityProviderException
+   */
+  protected static void readInlineCount(final JsonReader reader, final FeedMetadataImpl feedMetadata)
+      throws IOException, EntityProviderException {
+    if (reader.peek() == JsonToken.STRING && feedMetadata.getInlineCount() == null) {
+      int inlineCount;
+      try {
+        inlineCount = reader.nextInt();
+      } catch (final NumberFormatException e) {
+        throw new EntityProviderException(EntityProviderException.INLINECOUNT_INVALID.addContent(""), e);
+      }
+      if (inlineCount >= 0) {
+        feedMetadata.setInlineCount(inlineCount);
+      } else {
+        throw new EntityProviderException(EntityProviderException.INLINECOUNT_INVALID.addContent(inlineCount));
+      }
+    } else {
+      throw new EntityProviderException(EntityProviderException.INLINECOUNT_INVALID.addContent(reader.peek()));
+    }
+  }
+
+  /**
+   * 
+   * @param name
+   * @return ODataFeed
+   * @throws EdmException
+   * @throws EntityProviderException
+   * @throws IOException
+   */
+  protected ODataFeed readStartedInlineFeed(final String name) throws EdmException, EntityProviderException,
+      IOException {
+    // consume the already started content
+    handleName(name);
+    // consume the rest of the entry content
+    readFeedContent();
+    return new ODataDeltaFeedImpl(entries, feedMetadata);
+  }
+
+  /**
+   * 
+   * @return ODataFeed
+   * @throws EdmException
+   * @throws EntityProviderException
+   * @throws IOException
+   */
+  protected ODataFeed readInlineFeedStandalone() throws EdmException, EntityProviderException, IOException {
+    readFeed();
+    return new ODataDeltaFeedImpl(entries, feedMetadata);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/JsonPropertyDeserializer.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/JsonPropertyDeserializer.java b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/JsonPropertyDeserializer.java
new file mode 100644
index 0000000..44d8d07
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/JsonPropertyDeserializer.java
@@ -0,0 +1,326 @@
+/*******************************************************************************
+ * 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.client.core.ep.deserializer;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmFacets;
+import org.apache.olingo.odata2.api.edm.EdmLiteralKind;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.edm.EdmSimpleType;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeKind;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.client.api.ep.DeserializerProperties;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityComplexPropertyInfo;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityInfoAggregator;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityPropertyInfo;
+import org.apache.olingo.odata2.core.ep.util.FormatJson;
+
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonToken;
+
+/**
+ * JSON property consumer.
+ */
+public class JsonPropertyDeserializer {
+
+  /**
+   * Deserializes Property
+   * @param reader
+   * @param edmProperty
+   * @param readProperties
+   * @return Map<String, Object>
+   * @throws EntityProviderException
+   */
+  public Map<String, Object> readPropertyStandalone(JsonReader reader, final EdmProperty edmProperty,
+      final DeserializerProperties readProperties) throws EntityProviderException {
+    return readPropertyStandalone(reader, EntityInfoAggregator.create(edmProperty), readProperties);
+  }
+
+  /**
+   * Deserializes Property
+   * @param reader
+   * @param propertyInfo
+   * @param readProperties
+   * @return Map<String, Object>
+   * @throws EntityProviderException
+   */
+  public Map<String, Object> readPropertyStandalone(final JsonReader reader, final EntityPropertyInfo propertyInfo,
+      final DeserializerProperties readProperties) throws EntityProviderException {
+    Map<String, Object> typeMappings  = null ;
+    Map<String, Object> result = new HashMap<String, Object>();
+
+    try {
+      reader.beginObject();
+      String nextName = reader.nextName();
+      if (FormatJson.D.equals(nextName)) {
+        reader.beginObject();
+        nextName = reader.nextName();
+        handleName(reader, typeMappings, propertyInfo, readProperties, result, nextName);
+        reader.endObject();
+      } else {
+        handleName(reader, typeMappings, propertyInfo, readProperties, result, nextName);
+      }
+      reader.endObject();
+
+      if (reader.peek() != JsonToken.END_DOCUMENT) {
+        throw new EntityProviderException(EntityProviderException.END_DOCUMENT_EXPECTED.addContent(reader.peek()
+            .toString()));
+      }
+
+      return result;
+    } catch (final IOException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass()
+          .getSimpleName()), e);
+    } catch (final IllegalStateException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass()
+          .getSimpleName()), e);
+    }
+  }
+
+  /**
+   * This method reads through a collection of entities and deserializes each entry
+   * @param reader
+   * @param propertyInfo
+   * @param readProperties
+   * @return List<?>
+   * @throws EntityProviderException
+   */
+  public List<?> readCollection(JsonReader reader, final EntityPropertyInfo propertyInfo,
+        final DeserializerProperties readProperties) throws EntityProviderException {
+    final Object typeMapping =  null ;
+    List<Object> result = new ArrayList<Object>();
+    String name = null;
+    boolean wrapped = false;
+    boolean version2 = false;
+
+    try {
+      if (reader.peek() == JsonToken.BEGIN_OBJECT) {
+        reader.beginObject();
+        name = reader.nextName();
+        if (FormatJson.D.equals(name)) {
+          wrapped = true;
+          if (reader.peek() == JsonToken.BEGIN_OBJECT) {
+            reader.beginObject();
+            name = reader.nextName();
+          } else {
+            name = null;
+          }
+        }
+      }
+      if (name != null) {
+        version2 = true;
+        if (FormatJson.METADATA.equals(name)) {
+          readAndCheckTypeInfo(reader,
+              "Collection(" + propertyInfo.getType().getNamespace() + Edm.DELIMITER
+              + propertyInfo.getType().getName() + ")");
+          name = reader.nextName();
+        }
+        if (!FormatJson.RESULTS.equals(name)) {
+          throw new EntityProviderException(EntityProviderException.INVALID_PARENT_TAG
+              .addContent(FormatJson.RESULTS, name));
+        }
+      }
+      reader.beginArray();
+      while (reader.hasNext()) {
+        result.add(readPropertyValue(reader, propertyInfo, typeMapping, readProperties));
+      }
+      reader.endArray();
+      if (version2) {
+        reader.endObject();
+      }
+      if (wrapped) {
+        reader.endObject();
+      }
+
+      if (reader.peek() != JsonToken.END_DOCUMENT) {
+        throw new EntityProviderException(EntityProviderException.END_DOCUMENT_EXPECTED
+            .addContent(reader.peek().toString()));
+      }
+
+      return result;
+    } catch (final EdmException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED
+          .addContent(e.getClass().getSimpleName()), e);
+    } catch (final IOException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED
+          .addContent(e.getClass().getSimpleName()), e);
+    } catch (final IllegalStateException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED
+          .addContent(e.getClass().getSimpleName()), e);
+    }
+  }
+
+  private void handleName(final JsonReader reader, final Map<String, Object> typeMappings,
+      final EntityPropertyInfo entityPropertyInfo, final DeserializerProperties readProperties,
+      final Map<String, Object> result, final String nextName) throws EntityProviderException {
+    if (!entityPropertyInfo.getName().equals(nextName)) {
+      throw new EntityProviderException(EntityProviderException.ILLEGAL_ARGUMENT.addContent(nextName));
+    }
+    final Object mapping = typeMappings == null ? null : typeMappings.get(nextName);
+    final Object propertyValue = readPropertyValue(reader, entityPropertyInfo, mapping, readProperties);
+    result.put(nextName, propertyValue);
+  }
+
+  protected Object readPropertyValue(final JsonReader reader, final EntityPropertyInfo entityPropertyInfo,
+      final Object typeMapping, final DeserializerProperties readProperties)
+          throws EntityProviderException {
+    try {
+      return entityPropertyInfo.isComplex() ?
+          readComplexProperty(reader, (EntityComplexPropertyInfo) entityPropertyInfo, typeMapping, readProperties) :
+          readSimpleProperty(reader, entityPropertyInfo, typeMapping, readProperties);
+    } catch (final EdmException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass()
+          .getSimpleName()), e);
+    } catch (final IOException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass()
+          .getSimpleName()), e);
+    }
+  }
+
+  private Object readSimpleProperty(final JsonReader reader, final EntityPropertyInfo entityPropertyInfo,
+      final Object typeMapping, final DeserializerProperties readProperties)
+      throws EdmException, EntityProviderException, IOException {
+    final EdmSimpleType type = (EdmSimpleType) entityPropertyInfo.getType();
+    Object value = null;
+    final JsonToken tokenType = reader.peek();
+    if (tokenType == JsonToken.NULL) {
+      reader.nextNull();
+    } else {
+      switch (EdmSimpleTypeKind.valueOf(type.getName())) {
+      case Boolean:
+        if (tokenType == JsonToken.BOOLEAN) {
+          value = reader.nextBoolean();
+          value = value.toString();
+        } else {
+          throw new EntityProviderException(EntityProviderException.INVALID_PROPERTY_VALUE
+              .addContent(entityPropertyInfo.getName()));
+        }
+        break;
+      case Byte:
+      case SByte:
+      case Int16:
+      case Int32:
+        if (tokenType == JsonToken.NUMBER) {
+          value = reader.nextInt();
+          value = value.toString();
+        } else {
+          throw new EntityProviderException(EntityProviderException.INVALID_PROPERTY_VALUE
+              .addContent(entityPropertyInfo.getName()));
+        }
+        break;
+      case Single:
+      case Double:
+        if (tokenType == JsonToken.STRING) {
+          value = reader.nextString();
+        } else if (tokenType == JsonToken.NUMBER) {
+          value = reader.nextDouble();
+          value = value.toString();
+        } else {
+          throw new EntityProviderException(EntityProviderException.INVALID_PROPERTY_VALUE
+              .addContent(entityPropertyInfo.getName()));
+        }
+        break;
+      default:
+        if (tokenType == JsonToken.STRING) {
+          value = reader.nextString();
+        } else {
+          throw new EntityProviderException(EntityProviderException.INVALID_PROPERTY_VALUE
+              .addContent(entityPropertyInfo.getName()));
+        }
+        break;
+      }
+    }
+
+    final Class<?> typeMappingClass = typeMapping == null ? type.getDefaultType() : (Class<?>) typeMapping;
+    final EdmFacets facets = readProperties == null || readProperties.isValidatingFacets() ?
+        entityPropertyInfo.getFacets() : null;
+    return type.valueOfString((String) value, EdmLiteralKind.JSON, facets, typeMappingClass);
+  }
+
+  @SuppressWarnings("unchecked")
+  private Object readComplexProperty(final JsonReader reader, final EntityComplexPropertyInfo complexPropertyInfo,
+      final Object typeMapping, final DeserializerProperties readProperties)
+      throws EdmException, EntityProviderException, IOException {
+    if (reader.peek().equals(JsonToken.NULL)) {
+      reader.nextNull();
+      if ((readProperties == null || readProperties.isValidatingFacets()) && complexPropertyInfo.isMandatory()) {
+        throw new EntityProviderException(EntityProviderException.INVALID_PROPERTY_VALUE.addContent(complexPropertyInfo
+            .getName()));
+      }
+      return null;
+    }
+
+    reader.beginObject();
+    Map<String, Object> data = new HashMap<String, Object>();
+
+    Map<String, Object> mapping;
+    if (typeMapping != null) {
+      if (typeMapping instanceof Map) {
+        mapping = (Map<String, Object>) typeMapping;
+      } else {
+        throw new EntityProviderException(EntityProviderException.INVALID_MAPPING.addContent(complexPropertyInfo
+            .getName()));
+      }
+    } else {
+      mapping = new HashMap<String, Object>();
+    }
+
+    while (reader.hasNext()) {
+      final String childName = reader.nextName();
+      if (FormatJson.METADATA.equals(childName)) {
+        readAndCheckTypeInfo(reader,
+            complexPropertyInfo.getType().getNamespace() + Edm.DELIMITER + complexPropertyInfo.getType().getName());
+      } else {
+        EntityPropertyInfo childPropertyInfo = complexPropertyInfo.getPropertyInfo(childName);
+        if (childPropertyInfo == null) {
+          throw new EntityProviderException(EntityProviderException.INVALID_PROPERTY.addContent(childName));
+        }
+        Object childData = readPropertyValue(reader, childPropertyInfo, mapping.get(childName), readProperties);
+        if (data.containsKey(childName)) {
+          throw new EntityProviderException(EntityProviderException.DOUBLE_PROPERTY.addContent(childName));
+        }
+        data.put(childName, childData);
+      }
+    }
+    reader.endObject();
+    return data;
+  }
+
+  protected void readAndCheckTypeInfo(final JsonReader reader, String expectedTypeName)
+          throws IOException, EntityProviderException {
+    reader.beginObject();
+    if (!FormatJson.TYPE.equals(reader.nextName())) {
+      throw new EntityProviderException(EntityProviderException.MISSING_ATTRIBUTE.addContent(FormatJson.TYPE)
+          .addContent(FormatJson.METADATA));
+    }
+    final String actualTypeName = reader.nextString();
+    if (!expectedTypeName.equals(actualTypeName)) {
+      throw new EntityProviderException(EntityProviderException.INVALID_ENTITYTYPE.addContent(expectedTypeName)
+          .addContent(actualTypeName));
+    }
+    reader.endObject();
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/XmlEntityDeserializer.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/XmlEntityDeserializer.java b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/XmlEntityDeserializer.java
new file mode 100644
index 0000000..ea3393c
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/XmlEntityDeserializer.java
@@ -0,0 +1,190 @@
+/*******************************************************************************
+ * 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.client.core.ep.deserializer;
+
+import java.util.Map;
+
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.ep.entry.ODataEntry;
+import org.apache.olingo.odata2.api.ep.feed.ODataDeltaFeed;
+import org.apache.olingo.odata2.client.api.ep.EntityStream;
+import org.apache.olingo.odata2.core.commons.XmlHelper;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityInfoAggregator;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityPropertyInfo;
+
+/**
+ * Xml entity (content type dependent) consumer for reading input (from <code>content</code>).
+ * 
+ * 
+ */
+public class XmlEntityDeserializer {
+
+  /**
+   * 
+   * @throws EntityProviderException
+   */
+  public XmlEntityDeserializer() throws EntityProviderException {
+    super();
+  }
+
+  /**
+   * Returns an ODataDeltaFeed deserializing EntityStream
+   * @param entitySet
+   * @param entity
+   * @return ODataDeltaFeed
+   * @throws EntityProviderException
+   */
+  public ODataDeltaFeed readFeed(final EdmEntitySet entitySet, final EntityStream entity)
+      throws EntityProviderException {
+    XMLStreamReader reader = null;
+    EntityProviderException cachedException = null;
+
+    try {
+      reader = XmlHelper.createStreamReader(entity.getContent());
+
+      EntityInfoAggregator eia = EntityInfoAggregator.create(entitySet);
+      XmlFeedDeserializer xfc = new XmlFeedDeserializer();
+      return xfc.readFeed(reader, eia, entity.getReadProperties());
+    } catch (EntityProviderException e) {
+      cachedException = e;
+      throw cachedException;
+    } finally { //NOPMD  - suppressed
+      if (reader != null) {
+        try {
+          reader.close();
+        } catch (XMLStreamException e) {
+          if (cachedException != null) {
+            throw cachedException; //NOSONAR
+          } else {
+            throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.//NOSONAR
+                addContent(e.getClass() 
+                .getSimpleName()), e);
+          }
+        }
+      }
+    }
+  }
+
+  /**
+   * Returns an ODataEntry deserializing EntityStream
+   * @param entitySet
+   * @param entity
+   * @return ODataEntry
+   * @throws EntityProviderException
+   */
+  public ODataEntry readEntry(final EdmEntitySet entitySet, final EntityStream entity)
+      throws EntityProviderException {
+    XMLStreamReader reader = null;
+    EntityProviderException cachedException = null;
+
+    try {
+      reader = XmlHelper.createStreamReader(entity.getContent());
+      EntityInfoAggregator eia = EntityInfoAggregator.create(entitySet);
+
+      return new XmlEntryDeserializer().readEntry(reader, eia, entity.getReadProperties(), false);
+    } catch (EntityProviderException e) {
+      cachedException = e;
+      throw cachedException;
+    } finally {//NOPMD  - suppressed
+      if (reader != null) {
+        try {
+          reader.close();
+        } catch (XMLStreamException e) {
+          if (cachedException != null) {
+            throw cachedException; //NOSONAR
+          } else {
+            throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.//NOSONAR
+                addContent(e.getClass() 
+                .getSimpleName()), e); 
+          }
+        }
+      }
+    }
+  }
+  
+  /**
+   * 
+   * @param info
+   * @param entityStream
+   * @return
+   * @throws EntityProviderException
+   */
+  public Object readCollection(final EntityPropertyInfo info, EntityStream entityStream) 
+      throws EntityProviderException {
+    XMLStreamReader reader = null;
+    EntityProviderException cachedException = null;
+    try {
+      reader = XmlHelper.createStreamReader(entityStream.getContent());
+      return new XmlPropertyDeserializer().readCollection(reader, info, entityStream.getReadProperties());
+    } catch (final EntityProviderException e) {
+      cachedException = e;
+      throw cachedException;
+    } finally {// NOPMD (suppress DoNotThrowExceptionInFinally)
+      if (reader != null) {
+        try {
+          reader.close();
+        } catch (final XMLStreamException e) {
+          if (cachedException != null) {
+            throw cachedException;
+          } else {
+            throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED
+                .addContent(e.getClass().getSimpleName()), e);
+          }
+        }
+      }
+    }
+  }
+  
+  /**
+   * 
+   * @param propertyInfo
+   * @param entityStream
+   * @return
+   * @throws EntityProviderException
+   */
+  public Map<String, Object> readProperty(final EntityPropertyInfo propertyInfo, final EntityStream entityStream)
+      throws EntityProviderException {
+    XMLStreamReader reader = null;
+    EntityProviderException cachedException = null;
+    try {
+      reader = XmlHelper.createStreamReader(entityStream.getContent());
+      return new XmlPropertyDeserializer().readProperty(reader, propertyInfo, entityStream.getReadProperties());
+    } catch (EntityProviderException e) {
+      cachedException = e;
+      throw cachedException;
+    } finally {// NOPMD (suppress DoNotThrowExceptionInFinally)
+      if (reader != null) {
+        try {
+          reader.close();
+        } catch (XMLStreamException e) {
+          if (cachedException != null) {
+            throw cachedException;
+          } else {
+            throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass()
+                .getSimpleName()), e);
+          }
+        }
+      }
+    }
+  }
+}


[19/24] olingo-odata2 git commit: [OLINGO-1253]Client Module for Olingo v2

Posted by ar...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/XmlMetadataDeserializer.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/XmlMetadataDeserializer.java b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/XmlMetadataDeserializer.java
new file mode 100644
index 0000000..73d62c1
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/XmlMetadataDeserializer.java
@@ -0,0 +1,1570 @@
+/*******************************************************************************
+ * 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.client.core.ep.deserializer;
+
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmAction;
+import org.apache.olingo.odata2.api.edm.EdmAnnotationAttribute;
+import org.apache.olingo.odata2.api.edm.EdmAnnotationElement;
+import org.apache.olingo.odata2.api.edm.EdmAnnotations;
+import org.apache.olingo.odata2.api.edm.EdmAssociation;
+import org.apache.olingo.odata2.api.edm.EdmAssociationEnd;
+import org.apache.olingo.odata2.api.edm.EdmAssociationSet;
+import org.apache.olingo.odata2.api.edm.EdmAssociationSetEnd;
+import org.apache.olingo.odata2.api.edm.EdmComplexType;
+import org.apache.olingo.odata2.api.edm.EdmConcurrencyMode;
+import org.apache.olingo.odata2.api.edm.EdmContentKind;
+import org.apache.olingo.odata2.api.edm.EdmCustomizableFeedMappings;
+import org.apache.olingo.odata2.api.edm.EdmEntityContainer;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmEntityType;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmFacets;
+import org.apache.olingo.odata2.api.edm.EdmFunctionImport;
+import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
+import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
+import org.apache.olingo.odata2.api.edm.EdmParameter;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.edm.EdmReferentialConstraint;
+import org.apache.olingo.odata2.api.edm.EdmReferentialConstraintRole;
+import org.apache.olingo.odata2.api.edm.EdmSimpleType;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeKind;
+import org.apache.olingo.odata2.api.edm.EdmTypeKind;
+import org.apache.olingo.odata2.api.edm.FullQualifiedName;
+import org.apache.olingo.odata2.api.edm.provider.Facets;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.client.api.edm.EdmDataServices;
+import org.apache.olingo.odata2.client.api.edm.EdmSchema;
+import org.apache.olingo.odata2.client.api.edm.EdmUsing;
+import org.apache.olingo.odata2.client.core.edm.EdmMetadataAssociationEnd;
+import org.apache.olingo.odata2.client.core.edm.Impl.EdmAnnotationAttributeImpl;
+import org.apache.olingo.odata2.client.core.edm.Impl.EdmAnnotationElementImpl;
+import org.apache.olingo.odata2.client.core.edm.Impl.EdmAnnotationsImpl;
+import org.apache.olingo.odata2.client.core.edm.Impl.EdmAssociationEndImpl;
+import org.apache.olingo.odata2.client.core.edm.Impl.EdmAssociationImpl;
+import org.apache.olingo.odata2.client.core.edm.Impl.EdmAssociationSetEndImpl;
+import org.apache.olingo.odata2.client.core.edm.Impl.EdmAssociationSetImpl;
+import org.apache.olingo.odata2.client.core.edm.Impl.EdmComplexPropertyImpl;
+import org.apache.olingo.odata2.client.core.edm.Impl.EdmComplexTypeImpl;
+import org.apache.olingo.odata2.client.core.edm.Impl.EdmCustomizableFeedMappingsImpl;
+import org.apache.olingo.odata2.client.core.edm.Impl.EdmEntityContainerImpl;
+import org.apache.olingo.odata2.client.core.edm.Impl.EdmEntitySetImpl;
+import org.apache.olingo.odata2.client.core.edm.Impl.EdmEntityTypeImpl;
+import org.apache.olingo.odata2.client.core.edm.Impl.EdmFunctionImportImpl;
+import org.apache.olingo.odata2.client.core.edm.Impl.EdmFunctionImportParameter;
+import org.apache.olingo.odata2.client.core.edm.Impl.EdmImpl;
+import org.apache.olingo.odata2.client.core.edm.Impl.EdmKeyImpl;
+import org.apache.olingo.odata2.client.core.edm.Impl.EdmNamedImpl;
+import org.apache.olingo.odata2.client.core.edm.Impl.EdmNavigationPropertyImpl;
+import org.apache.olingo.odata2.client.core.edm.Impl.EdmOnDeleteImpl;
+import org.apache.olingo.odata2.client.core.edm.Impl.EdmParameterImpl;
+import org.apache.olingo.odata2.client.core.edm.Impl.EdmPropertyImpl;
+import org.apache.olingo.odata2.client.core.edm.Impl.EdmPropertyRefImpl;
+import org.apache.olingo.odata2.client.core.edm.Impl.EdmReferentialConstraintImpl;
+import org.apache.olingo.odata2.client.core.edm.Impl.EdmReferentialConstraintRoleImpl;
+import org.apache.olingo.odata2.client.core.edm.Impl.EdmSchemaImpl;
+import org.apache.olingo.odata2.client.core.edm.Impl.EdmSimplePropertyImpl;
+import org.apache.olingo.odata2.client.core.edm.Impl.EdmTypedImpl;
+import org.apache.olingo.odata2.client.core.edm.Impl.EdmUsingImpl;
+import org.apache.olingo.odata2.core.commons.XmlHelper;
+import org.apache.olingo.odata2.core.edm.EdmSimpleTypeFacadeImpl;
+import org.apache.olingo.odata2.core.ep.util.XmlMetadataConstants;
+
+/**
+ * This class deserializes Metadata document
+ *
+ */
+public class XmlMetadataDeserializer {
+
+  private Map<String, Set<String>> inscopeMap = new HashMap<String, Set<String>>();
+  private Map<String, String> aliasNamespaceMap = new HashMap<String, String>();
+  private Map<String, String> xmlNamespaceMap;
+  private Map<String, String> mandatoryNamespaces;
+  private Map<FullQualifiedName, EdmEntityType> entityTypesMap = new HashMap<FullQualifiedName, EdmEntityType>();
+  private Map<FullQualifiedName, EdmComplexType> complexTypesMap = new HashMap<FullQualifiedName, EdmComplexType>();
+  private Map<FullQualifiedName, EdmProperty> complexPropertyMap = new HashMap<FullQualifiedName, EdmProperty>();
+  private Map<FullQualifiedName, EdmAssociation> associationsMap = new HashMap<FullQualifiedName, EdmAssociation>();
+  private Map<String, EdmAssociationSet> associationSetMap = new HashMap<String, EdmAssociationSet>();
+  private Map<String, EdmAssociationSet> tempAssociationSetMap = new HashMap<String, EdmAssociationSet>();
+   private Map<String, List<EdmAssociationSetEndImpl>> associationSetEndMap = 
+      new HashMap<String, List<EdmAssociationSetEndImpl>>();
+  private Map<FullQualifiedName, EdmEntityContainer> containerMap =
+      new HashMap<FullQualifiedName, EdmEntityContainer>();
+  //Map for base type relation
+  private Map<FullQualifiedName, FullQualifiedName> entityBaseTypeMap = 
+      new HashMap<FullQualifiedName, FullQualifiedName>();
+  private Map<FullQualifiedName, FullQualifiedName> complexBaseTypeMap = 
+      new HashMap<FullQualifiedName, FullQualifiedName>();
+   private List<EdmFunctionImport> edmFunctionImportList = new ArrayList<EdmFunctionImport>();
+  private List<EdmEntitySet> edmEntitySetList = new ArrayList<EdmEntitySet>();
+  private List<EdmNavigationProperty> navProperties = new ArrayList<EdmNavigationProperty>();
+  private String currentHandledStartTagName;
+  private String currentNamespace;
+  private String edmNamespace = Edm.NAMESPACE_EDM_2008_09;
+  private Set<String> edmNamespaces;
+  private EdmEntityContainer defaultEdmEntityContainer;
+
+  /**
+   * 
+   * @param content
+   * @param validate
+   * @return EdmDataServices
+   * @throws EntityProviderException
+   * @throws EdmException
+   */
+  public EdmDataServices readMetadata(final InputStream content, final boolean validate)//NOSONAR
+      throws EntityProviderException, EdmException { 
+    try {
+      initialize();
+      EdmDataServices dataServices = new EdmDataServices();
+      List<EdmSchema> schemas = new ArrayList<EdmSchema>();
+      EdmImpl edm = new EdmImpl();
+      XMLStreamReader reader = XmlHelper.createStreamReader(content);
+      while (reader.hasNext()
+          && !(reader.isEndElement() && Edm.NAMESPACE_EDMX_2007_06.equals(reader.getNamespaceURI())
+              && XmlMetadataConstants.EDMX_TAG.equals(reader.getLocalName()))) {
+        reader.next();
+        if (reader.isStartElement()) {
+          extractNamespaces(reader);
+          if (XmlMetadataConstants.EDM_SCHEMA.equals(reader.getLocalName())) { //NOSONAR
+            edmNamespace = reader.getNamespaceURI();
+            checkEdmNamespace();
+            schemas.add(readSchema(reader, edm));
+          } else if (XmlMetadataConstants.EDM_DATA_SERVICES.equals(reader
+              .getLocalName())) {
+            dataServices.setDataServiceVersion(reader.getAttributeValue(Edm.NAMESPACE_M_2007_08, "DataServiceVersion"));
+          }
+        }
+      }
+
+      if (!reader.isEndElement() || !XmlMetadataConstants.EDMX_TAG.equals(reader.getLocalName())) {
+        throw new EntityProviderException(EntityProviderException.MISSING_TAG
+            .addContent(XmlMetadataConstants.EDMX_TAG));
+      }
+
+      setBaseTypeForEntityType();
+      setBaseTypeForComplexType();
+      setDetailsForEntitySet();
+      setAssociationSetForNavigations();
+      if (validate) {
+        validate();
+      }
+      edm.setEdmSchemas(schemas);
+      dataServices.setClientEdm(edm);
+      reader.close();
+      return dataServices;
+    } catch (XMLStreamException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass()
+          .getSimpleName()), e);
+    }
+
+  }
+
+  private EdmSchema readSchema(final XMLStreamReader reader, EdmImpl edm) //NOSONAR
+      throws XMLStreamException, EntityProviderException, EdmException { 
+    reader.require(XMLStreamConstants.START_ELEMENT, edmNamespace, XmlMetadataConstants.EDM_SCHEMA);
+    final EdmSchemaImpl schemaImpl = new EdmSchemaImpl();
+    final List<EdmUsing> usings = new ArrayList<EdmUsing>();
+    final List<EdmComplexType> complexTypes = new ArrayList<EdmComplexType>();
+    final List<EdmEntityType> entityTypes = new ArrayList<EdmEntityType>();
+    final List<EdmAssociation> associations = new ArrayList<EdmAssociation>();
+    final List<EdmEntityContainer> entityContainers = new ArrayList<EdmEntityContainer>();
+    final List<EdmAnnotationElement> annotationElements = new ArrayList<EdmAnnotationElement>();
+    schemaImpl.setNamespace(reader.getAttributeValue(null, XmlMetadataConstants.EDM_SCHEMA_NAMESPACE));
+    inscopeMap.put(schemaImpl.getNamespace(), new HashSet<String>());
+    schemaImpl.setAlias(reader.getAttributeValue(null, XmlMetadataConstants.EDM_SCHEMA_ALIAS));
+    schemaImpl.setAnnotationAttributes(readAnnotationAttribute(reader));
+    currentNamespace = schemaImpl.getNamespace();
+    while (reader.hasNext()
+        && !(reader.isEndElement() && edmNamespace.equals(reader.getNamespaceURI())
+            && XmlMetadataConstants.EDM_SCHEMA.equals(reader.getLocalName()))) {
+      reader.next();
+      if (reader.isStartElement()) {
+        extractNamespaces(reader);
+        currentHandledStartTagName = reader.getLocalName();
+        if (XmlMetadataConstants.EDM_USING.equals(currentHandledStartTagName)) {
+          usings.add(readUsing(reader, schemaImpl.getNamespace()));
+        } else if (XmlMetadataConstants.EDM_ENTITY_TYPE.equals(currentHandledStartTagName)) {
+          entityTypes.add(readEntityType(reader, edm));
+        } else if (XmlMetadataConstants.EDM_COMPLEX_TYPE.equals(currentHandledStartTagName)) {
+          complexTypes.add(readComplexType(reader, edm));
+        } else if (XmlMetadataConstants.EDM_ASSOCIATION.equals(currentHandledStartTagName)) {
+          associations.add(readAssociation(reader, edm));
+        } else if (XmlMetadataConstants.EDM_ENTITY_CONTAINER.equals(currentHandledStartTagName)) {
+          entityContainers.add(readEntityContainer(reader, (EdmImpl) edm));
+        } else {
+          annotationElements.add(readAnnotationElement(reader));
+        }
+      }
+    }
+    if (schemaImpl.getAlias() != null) {
+      aliasNamespaceMap.put(schemaImpl.getAlias(), schemaImpl.getNamespace());
+      edm.setAliasToNamespaceInfo(aliasNamespaceMap);
+    }
+    if (!annotationElements.isEmpty()) {
+      schemaImpl.setAnnotationElements(annotationElements);
+    }
+    schemaImpl
+        .setUsings(usings)
+        .setEntityTypes(entityTypes)
+        .setComplexTypes(complexTypes)
+        .setAssociations(associations)
+        .setEntityContainers(entityContainers);
+
+    edm.setAliasToNamespaceInfo(aliasNamespaceMap)
+        .setEdmAssociations(associationsMap)
+        .setEdmComplexTypes(complexTypesMap)
+        .setEdmEntityContainers(containerMap)
+        .setDefaultEntityContainer(defaultEdmEntityContainer)
+        .setEdmEntitySets(edmEntitySetList)
+        .setEdmEntityTypes(entityTypesMap)
+        .setEdmFunctionImports(edmFunctionImportList);
+
+
+    return schemaImpl;
+  }
+
+  private void setAssociationSetForNavigations() throws EdmException {
+    for(EdmEntitySet edmEntitySet:edmEntitySetList){
+      List<String> navigations =  edmEntitySet.getEntityType().getNavigationPropertyNames();
+      if(navigations!=null && !navigations.isEmpty()){
+        for (EdmNavigationProperty navigationProperty : navProperties) {
+          if (navigations.contains(navigationProperty.getName())) { //NOSONAR
+            FullQualifiedName associationName = ((EdmNavigationPropertyImpl) navigationProperty).getRelationshipName();
+            String toRoleName = ((EdmNavigationPropertyImpl) navigationProperty).getToRole();
+            EdmAssociationEnd end = associationsMap.get(associationName).getEnd(toRoleName);
+            if (end == null) {
+              throw new EdmException(EdmException.ASSOCIATIONNOTFOUND);
+            }
+            String relation = associationName.toString();
+            StringBuilder key = new StringBuilder();
+            key.append(edmEntitySet.getName());
+            key.append(">>");
+            key.append(relation);
+            key.append(">>");
+            key.append(navigationProperty.getFromRole());
+            ((EdmNavigationPropertyImpl) navigationProperty).setMultiplicity(end.getMultiplicity());
+            associationSetMap.put(key.toString(), tempAssociationSetMap.get(relation));
+          }
+        }
+      }
+    }
+  }
+
+  private void setDetailsForEntitySet() throws EdmException {
+    for (EdmEntitySet entitySet : edmEntitySetList) {
+      EdmEntitySetImpl entitySetImpl = (EdmEntitySetImpl) entitySet;
+      FullQualifiedName entityTypeKey = entitySetImpl.getEntityTypeName();
+      if(aliasNamespaceMap.get(entitySetImpl.getEntityTypeName().getNamespace()) != null){
+        entityTypeKey = new FullQualifiedName(aliasNamespaceMap.get(entitySetImpl.getEntityTypeName().getNamespace()),
+            entitySetImpl.getEntityTypeName().getName());
+      }
+      if (entitySetImpl.getEntityType() == null && entityTypeKey != null) {
+        if(entityTypesMap.get(entityTypeKey) != null){
+          entitySetImpl.setEdmEntityType(entityTypesMap.get(entityTypeKey));
+        }else{
+          EdmEntityTypeImpl edmEntityType = new EdmEntityTypeImpl();
+          edmEntityType.setName(entitySetImpl.getEntityTypeName().getName());
+          edmEntityType.setNamespace(entitySetImpl.getEntityTypeName().getNamespace());
+          entitySetImpl.setEdmEntityType(edmEntityType);
+        }
+      }
+      if (associationSetEndMap.get(entitySet.getName())!=null) {
+         List<EdmAssociationSetEndImpl> ends = associationSetEndMap.get(entitySet.getName());
+         for(EdmAssociationSetEndImpl end:ends){
+           end.setEntitySet(entitySet);
+         }
+      }
+    }
+
+  }
+
+  private void setBaseTypeForComplexType() throws EdmException {
+    for (Entry<FullQualifiedName, EdmComplexType> entity : complexTypesMap.entrySet()) {
+      EdmComplexTypeImpl entityType = (EdmComplexTypeImpl) entity.getValue();
+      if (((EdmComplexTypeImpl) entity.getValue()).getEdmBaseTypeName() != null && 
+          entity.getValue().getBaseType() == null) {
+        FullQualifiedName fqname = entityType.getEdmBaseTypeName();
+        if(complexTypesMap.get(entityType.getEdmBaseTypeName()) != null){
+          entityType.setEdmBaseType(complexTypesMap.get(fqname));
+        }else if (aliasNamespaceMap.containsKey(fqname.getNamespace())) {
+          FullQualifiedName changedName = new FullQualifiedName(
+              aliasNamespaceMap.get(fqname.getNamespace()), fqname.getName());
+          entityType.setEdmBaseType(complexTypesMap.get(changedName));
+        }else{
+          //Adding dummy basetype awhich will fail during validation
+          EdmComplexTypeImpl newBaseType = new EdmComplexTypeImpl();
+          newBaseType.setName(fqname.getName());
+          newBaseType.setNamespace(fqname.getNamespace());
+          ((EdmComplexTypeImpl) entity.getValue()).setEdmBaseType(newBaseType);
+           break;
+        }
+        
+      }
+    }
+    setBaseTypePropertiesForComplexType(complexBaseTypeMap);
+  }
+
+  private void setBaseTypeForEntityType() throws EdmException {
+    for (Entry<FullQualifiedName, EdmEntityType> entity : entityTypesMap.entrySet()) {
+      EdmEntityTypeImpl entityType = (EdmEntityTypeImpl) entity.getValue();
+      if (entityType.getBaseTypeName() != null && entity.getValue()
+          .getBaseType() == null) {
+        FullQualifiedName fqname = entityType.getBaseTypeName();
+        if (entityTypesMap.get(entityType.getBaseTypeName()) != null) {
+          entityType.setEdmBaseType(entityTypesMap.get(fqname));
+        } else if (aliasNamespaceMap.containsKey(fqname.getNamespace())) {
+          FullQualifiedName changedName = new FullQualifiedName(
+              aliasNamespaceMap.get(fqname.getNamespace()), fqname.getName());
+          entityType.setEdmBaseType(entityTypesMap.get(changedName));
+        } else {// Adding dummy basetype which will fail during validation
+          EdmEntityTypeImpl newBaseType = new EdmEntityTypeImpl();
+          newBaseType.setName(fqname.getName());
+          newBaseType.setNamespace(fqname.getNamespace());
+          entityType.setEdmBaseType(newBaseType);
+          break;
+        }
+      }
+    }
+    setBaseTypePropertiesForEntityType(entityBaseTypeMap);
+  }
+
+  private void setBaseTypePropertiesForEntityType(
+      Map<FullQualifiedName, FullQualifiedName> baseTypeMap) throws EdmException{
+    changeAliasNamespaces(baseTypeMap);
+    while(!baseTypeMap.isEmpty()){
+      Iterator<Entry<FullQualifiedName, FullQualifiedName>> iterator = baseTypeMap.entrySet().iterator();
+      while (iterator.hasNext()) {
+        Entry<FullQualifiedName, FullQualifiedName> baseType = iterator.next();
+        if(baseTypeMap.get(baseType.getValue()) == null){
+          EdmEntityType entityType = entityTypesMap.get(baseType.getKey());
+          List<String> properties = entityType.getPropertyNames();
+          if(entityTypesMap.get(baseType.getValue())!=null){ //NOSONAR
+            properties.addAll(entityTypesMap.get(baseType.getValue()).getPropertyNames());
+          }
+          iterator.remove();
+        }
+      }
+    }
+  }
+  private void setBaseTypePropertiesForComplexType(
+      Map<FullQualifiedName, FullQualifiedName> baseTypeMap) throws EdmException{
+    changeAliasNamespaces(baseTypeMap);
+    while(!baseTypeMap.isEmpty()){
+      Iterator<Entry<FullQualifiedName, FullQualifiedName>> iterator = baseTypeMap.entrySet().iterator();
+      while (iterator.hasNext()) {
+        Entry<FullQualifiedName, FullQualifiedName> baseType = iterator.next();
+        if(baseTypeMap.get(baseType.getValue()) == null){
+          EdmComplexType entityType = complexTypesMap.get(baseType.getKey());
+          List<String> properties = entityType.getPropertyNames();
+          if(complexTypesMap.get(baseType.getValue())!=null){ //NOSONAR
+            properties.addAll(complexTypesMap.get(baseType.getValue()).getPropertyNames());
+          }
+          iterator.remove();
+        }
+      }
+    }
+  }
+  private void changeAliasNamespaces(Map<FullQualifiedName, FullQualifiedName> baseTypeMap) {
+    for(Entry<FullQualifiedName, FullQualifiedName> entry:baseTypeMap.entrySet()){
+      if (aliasNamespaceMap.containsKey(entry.getKey().getNamespace())) {
+        FullQualifiedName value = baseTypeMap.get(entry.getKey());
+        FullQualifiedName name = new FullQualifiedName(aliasNamespaceMap.get(entry.getKey().getNamespace()), 
+            entry.getKey().getName());
+        baseTypeMap.put(name, value);
+        baseTypeMap.remove(entry.getKey());
+      }
+      if (aliasNamespaceMap.containsKey(entry.getValue().getNamespace())) {
+        FullQualifiedName value =  new FullQualifiedName(aliasNamespaceMap.get(entry.getValue().getNamespace()), 
+            entry.getValue().getName());
+        baseTypeMap.remove(entry.getKey());
+        baseTypeMap.put(entry.getKey(), value);
+      }
+     
+    }
+    
+  }
+
+  private EdmUsingImpl readUsing(final XMLStreamReader reader, final String schemaNamespace)
+      throws XMLStreamException, EntityProviderException {
+
+    reader.require(XMLStreamConstants.START_ELEMENT, edmNamespace, XmlMetadataConstants.EDM_USING);
+
+    EdmUsingImpl using = new EdmUsingImpl();
+    using.setNamespace(reader.getAttributeValue(null, XmlMetadataConstants.EDM_SCHEMA_NAMESPACE));
+    inscopeMap.get(schemaNamespace).add(using.getNamespace());
+    using.setAlias(reader.getAttributeValue(null, XmlMetadataConstants.EDM_SCHEMA_ALIAS));
+    using.setAnnotationAttributes(readAnnotationAttribute(reader));
+
+    List<EdmAnnotationElement> annotationElements = new ArrayList<EdmAnnotationElement>();
+    while (reader.hasNext() && !(reader.isEndElement() && edmNamespace.equals(reader.getNamespaceURI())
+        && XmlMetadataConstants.EDM_USING.equals(reader.getLocalName()))) {
+
+      reader.next();
+      if (reader.isStartElement()) {
+        extractNamespaces(reader);
+        currentHandledStartTagName = reader.getLocalName();
+        annotationElements.add(readAnnotationElement(reader));
+      }
+    }
+    if (!annotationElements.isEmpty()) {
+      using.setAnnotationElements(annotationElements);
+    }
+
+    if (using.getAlias() != null) {
+      aliasNamespaceMap.put(using.getAlias(), using.getNamespace());
+    }
+
+    return using;
+  }
+
+  private EdmEntityContainer readEntityContainer(final XMLStreamReader reader, EdmImpl edm)//NOSONAR
+      throws XMLStreamException, EntityProviderException, EdmException { 
+    reader.require(XMLStreamConstants.START_ELEMENT, edmNamespace, XmlMetadataConstants.EDM_ENTITY_CONTAINER);
+    EdmEntityContainerImpl container = new EdmEntityContainerImpl(edm);
+    List<EdmAnnotationElement> annotationElements = new ArrayList<EdmAnnotationElement>();
+
+    List<EdmEntitySet> edmEntitySets = new ArrayList<EdmEntitySet>();
+    List<EdmFunctionImport> edmFunctionImports = new ArrayList<EdmFunctionImport>();
+    List<EdmAssociationSet> edmAssociationSets = new ArrayList<EdmAssociationSet>();
+
+    container.setName(reader.getAttributeValue(null, XmlMetadataConstants.EDM_NAME));
+    if (reader.getAttributeValue(Edm.NAMESPACE_M_2007_08, XmlMetadataConstants.EDM_CONTAINER_IS_DEFAULT) != null) {
+      container.setDefaultContainer(
+          "true".equalsIgnoreCase(reader.getAttributeValue(Edm.NAMESPACE_M_2007_08,
+              "IsDefaultEntityContainer")));
+      defaultEdmEntityContainer = container;
+    }
+    container.setExtendz(reader.getAttributeValue(null, XmlMetadataConstants.EDM_CONTAINER_EXTENDZ));
+    List<EdmAnnotationAttribute> annotationAttribute = readAnnotationAttribute(reader);
+    EdmAnnotationsImpl annotations = new EdmAnnotationsImpl();
+    annotations.setAnnotationAttributes(annotationAttribute);
+    container.setAnnotations(annotations);
+
+    while (reader.hasNext()
+        && !(reader.isEndElement() && edmNamespace.equals(reader.getNamespaceURI())
+            && XmlMetadataConstants.EDM_ENTITY_CONTAINER.equals(reader.getLocalName()))) {
+      reader.next();
+      if (reader.isStartElement()) {
+        extractNamespaces(reader);
+        currentHandledStartTagName = reader.getLocalName();
+        if (XmlMetadataConstants.EDM_ENTITY_SET.equals(currentHandledStartTagName)) {
+          EdmEntitySetImpl entity = readEntitySet(reader);
+          entity.setEdmEntityContainer(container);
+          edmEntitySets.add(entity);
+        } else if (XmlMetadataConstants.EDM_ASSOCIATION_SET.equals(currentHandledStartTagName)) {
+          EdmAssociationSet association = readAssociationSet(reader, edm);
+          edmAssociationSets.add(association);
+        } else if (XmlMetadataConstants.EDM_FUNCTION_IMPORT.equals(currentHandledStartTagName)) {
+          edmFunctionImports.add(readFunctionImport(reader, edm));
+        } else {
+          annotationElements.add(readAnnotationElement(reader));
+        }
+      }
+    }
+    if (!annotationElements.isEmpty()) {
+      annotations.setAnnotationElements(annotationElements);
+      container.setAnnotations(annotations);
+    }
+    if (edmFunctionImports != null && !edmFunctionImports.isEmpty()) {
+      setContainerInFunctionImport(edmFunctionImports, container);
+    }
+    if (edmAssociationSets != null && !edmAssociationSets.isEmpty()) {
+      setConatinerInAssociationSet(edmAssociationSets, container);
+    }
+    container.setEdmEntitySets(edmEntitySets).setEdmAssociationSets(edmAssociationSets).setEdmFunctionImports(
+        edmFunctionImports);
+
+    containerMap.put(new FullQualifiedName(currentNamespace, container.getName()),
+        container);
+    edmEntitySetList.addAll(edmEntitySets);
+    edmFunctionImportList.addAll(edmFunctionImports);
+    return container;
+  }
+
+  private void setConatinerInAssociationSet(List<EdmAssociationSet> edmAssociationSets,
+      EdmEntityContainerImpl containerImpl) {
+    for (EdmAssociationSet associationSet : edmAssociationSets) {
+      EdmAssociationSetImpl assocationSetImpl = (EdmAssociationSetImpl) associationSet;
+      assocationSetImpl.setEdmEntityContainer(containerImpl);
+    }
+    containerImpl.setEdmAssociationSetMap(associationSetMap);
+  }
+
+  /**
+   * @param functionImports
+   * @param containerImpl
+   */
+  private void setContainerInFunctionImport(List<EdmFunctionImport> functionImports,
+      EdmEntityContainerImpl containerImpl) {
+    for (EdmFunctionImport funcImport : functionImports) {
+      EdmFunctionImportImpl functionImpl = (EdmFunctionImportImpl) funcImport;
+      functionImpl.setEdmEntityContainer(containerImpl);
+    }
+  }
+
+  private EdmFunctionImport readFunctionImport(final XMLStreamReader reader, EdmImpl edm)
+      throws XMLStreamException, EntityProviderException, EdmException {
+    reader.require(XMLStreamConstants.START_ELEMENT, edmNamespace, XmlMetadataConstants.EDM_FUNCTION_IMPORT);
+    EdmFunctionImportImpl function = new EdmFunctionImportImpl();
+    ArrayList<EdmFunctionImportParameter> functionImportParameters = new ArrayList<EdmFunctionImportParameter>();
+    Map<String, ArrayList<EdmFunctionImportParameter>> functionParameters =
+        new HashMap<String, ArrayList<EdmFunctionImportParameter>>();
+    List<EdmAnnotationElement> annotationElements = new ArrayList<EdmAnnotationElement>();
+    EdmAnnotationsImpl annotations = new EdmAnnotationsImpl();
+    Map<String, EdmParameter> edmParamMap = new HashMap<String, EdmParameter>();
+    List<String> parametersList =  new ArrayList<String>();
+
+    function.setName(reader.getAttributeValue(null, XmlMetadataConstants.EDM_NAME));
+    function.setHttpMethod(reader.getAttributeValue(Edm.NAMESPACE_M_2007_08,
+        XmlMetadataConstants.EDM_FUNCTION_IMPORT_HTTP_METHOD));
+    function.setEntitySet(reader.getAttributeValue(null, XmlMetadataConstants.EDM_ENTITY_SET));
+
+    String returnTypeString = reader.getAttributeValue(null, XmlMetadataConstants.EDM_FUNCTION_IMPORT_RETURN);
+    EdmTypedImpl returnType = new EdmTypedImpl();
+    if (returnTypeString != null) {
+      if (returnTypeString.startsWith("Collection") || returnTypeString.startsWith("collection")) {
+        returnType.setMultiplicity(EdmMultiplicity.MANY);
+        returnTypeString = returnTypeString.substring(returnTypeString.indexOf("(") + 1, returnTypeString.length() - 1);
+      } else {
+        returnType.setMultiplicity(EdmMultiplicity.ONE);
+      }
+      FullQualifiedName fqName = extractFQName(returnTypeString);
+      returnType.setTypeName(fqName);
+      ((EdmNamedImpl) returnType).setName(fqName.getName());
+      ((EdmNamedImpl) returnType).setEdm(edm);
+      function.setReturnType(returnType);
+    }
+    annotations.setAnnotationAttributes(readAnnotationAttribute(reader));
+    while (reader.hasNext()
+        && !(reader.isEndElement() && edmNamespace.equals(reader.getNamespaceURI())
+            && XmlMetadataConstants.EDM_FUNCTION_IMPORT.equals(reader.getLocalName()))) {
+      reader.next();
+      if (reader.isStartElement()) {
+        extractNamespaces(reader);
+        currentHandledStartTagName = reader.getLocalName();
+        if (XmlMetadataConstants.EDM_FUNCTION_PARAMETER.equals(currentHandledStartTagName)) {
+          EdmFunctionImportParameter edmFunctionImportParameter = readFunctionImportParameter(reader);
+          functionImportParameters.add(edmFunctionImportParameter);
+          EdmParameterImpl edmParamImpl = new EdmParameterImpl();
+          edmParamImpl.setEdm(edm);
+          edmParamImpl.setName(edmFunctionImportParameter.getName());
+          edmParamImpl.setFacets(edmFunctionImportParameter.getFacets());
+          edmParamImpl.setMapping(edmFunctionImportParameter.getMapping());
+          edmParamImpl.setMultiplicity(returnType.getMultiplicity());
+          edmParamImpl.setParameter(edmFunctionImportParameter);
+          edmParamImpl.setTypeName(edmFunctionImportParameter.getType().getFullQualifiedName());
+          edmParamImpl.setAnnotations(edmFunctionImportParameter.getAnnotations());
+          parametersList.add(edmParamImpl.getName());
+          edmParamMap.put(edmFunctionImportParameter.getName(), edmParamImpl);
+        } else {
+          annotationElements.add(readAnnotationElement(reader));
+        }
+      }
+    }
+    if (!annotationElements.isEmpty()) {
+      annotations.setAnnotationElements(annotationElements);
+    }
+    function.setAnnotations(annotations);
+    functionParameters.put(function.getName(), functionImportParameters);
+    function.setParameters(functionParameters);
+    function.setEdmParameters(edmParamMap);
+    function.setParametersList(parametersList);
+    return function;
+  }
+
+  private EdmFunctionImportParameter readFunctionImportParameter(final XMLStreamReader reader)
+      throws EntityProviderException, XMLStreamException, EdmException {
+    reader.require(XMLStreamConstants.START_ELEMENT, edmNamespace, XmlMetadataConstants.EDM_FUNCTION_PARAMETER);
+    EdmFunctionImportParameter functionParameter = new EdmFunctionImportParameter();
+    EdmAnnotationsImpl annotations = new EdmAnnotationsImpl();
+    List<EdmAnnotationElement> annotationElements = new ArrayList<EdmAnnotationElement>();
+
+    functionParameter.setName(reader.getAttributeValue(null, XmlMetadataConstants.EDM_NAME));
+    functionParameter.setMode(reader.getAttributeValue(null, XmlMetadataConstants.EDM_FUNCTION_PARAMETER_MODE));
+    String type = reader.getAttributeValue(null, XmlMetadataConstants.EDM_TYPE);
+    if (type == null) {
+      throw new EntityProviderException(EntityProviderException.MISSING_ATTRIBUTE
+          .addContent(XmlMetadataConstants.EDM_TYPE).addContent(XmlMetadataConstants.EDM_FUNCTION_PARAMETER));
+    }
+    functionParameter.setType(EdmSimpleTypeKind.valueOf(extractFQName(type).getName()));
+    EdmFacets facets = readFacets(reader);
+    functionParameter.setFacets(facets);
+    annotations.setAnnotationAttributes(readAnnotationAttribute(reader));
+    while (reader.hasNext()
+        && !(reader.isEndElement() && edmNamespace.equals(reader.getNamespaceURI())
+            && XmlMetadataConstants.EDM_FUNCTION_PARAMETER.equals(reader.getLocalName()))) {
+      reader.next();
+      if (reader.isStartElement()) {
+        extractNamespaces(reader);
+        annotationElements.add(readAnnotationElement(reader));
+      }
+    }
+    if (!annotationElements.isEmpty()) {
+      annotations.setAnnotationElements(annotationElements);
+    }
+    functionParameter.setAnnotations(annotations);
+    return functionParameter;
+  }
+
+  private EdmAssociationSet readAssociationSet(final XMLStreamReader reader, EdmImpl edm)
+      throws XMLStreamException, EntityProviderException, EdmException {
+    reader.require(XMLStreamConstants.START_ELEMENT, edmNamespace, XmlMetadataConstants.EDM_ASSOCIATION_SET);
+    EdmAssociationSetImpl associationSet = new EdmAssociationSetImpl();
+    List<EdmAssociationSetEnd> ends = new ArrayList<EdmAssociationSetEnd>();
+    EdmAnnotationsImpl annotation = new EdmAnnotationsImpl();
+    String entitySetName = null;
+    List<EdmAnnotationElement> annotationElements = new ArrayList<EdmAnnotationElement>();
+    associationSet.setName(reader.getAttributeValue(null, XmlMetadataConstants.EDM_NAME));
+    String association = reader.getAttributeValue(null, XmlMetadataConstants.EDM_ASSOCIATION);
+    if (association != null) {
+      associationSet.setAssociation(extractFQName(association));
+    } else {
+      throw new EntityProviderException(EntityProviderException.MISSING_ATTRIBUTE
+          .addContent(XmlMetadataConstants.EDM_ASSOCIATION).addContent(XmlMetadataConstants.EDM_ASSOCIATION_SET));
+    }
+    annotation.setAnnotationAttributes(readAnnotationAttribute(reader));
+    while (reader.hasNext()
+        && !(reader.isEndElement() && edmNamespace.equals(reader.getNamespaceURI())
+            && XmlMetadataConstants.EDM_ASSOCIATION_SET.equals(reader.getLocalName()))) {
+      reader.next();
+      if (reader.isStartElement()) {
+        extractNamespaces(reader);
+        currentHandledStartTagName = reader.getLocalName();
+        if (XmlMetadataConstants.EDM_ASSOCIATION_END.equals(currentHandledStartTagName)) {
+          EdmAssociationSetEndImpl associationSetEnd = new EdmAssociationSetEndImpl();
+          entitySetName = reader.getAttributeValue(null, XmlMetadataConstants.EDM_ENTITY_SET);
+          associationSetEnd.setEntitySetName(entitySetName);
+          associationSetEnd.setRole(reader.getAttributeValue(null, XmlMetadataConstants.EDM_ROLE));
+          ends.add(associationSetEnd);
+          List<EdmAssociationSetEndImpl> associationSetEndList;
+          if(associationSetEndMap.get(entitySetName) == null){
+            associationSetEndList = new ArrayList<EdmAssociationSetEndImpl>();
+          }else{
+            associationSetEndList= associationSetEndMap.get(entitySetName);
+          }
+          associationSetEndList.add(associationSetEnd);
+          associationSetEndMap.put(entitySetName, associationSetEndList);
+        } else {
+          annotationElements.add(readAnnotationElement(reader));
+        }
+      }
+    }
+    if (ends.size() != 2) {
+      throw new EntityProviderException(EntityProviderException.ILLEGAL_ARGUMENT
+          .addContent("Count of AssociationSet ends should be 2"));
+    } else {
+      associationSet.setEnd1(ends.get(0));
+      associationSet.setEnd2(ends.get(1));
+    }
+    if (!annotationElements.isEmpty()) {
+      annotation.setAnnotationElements(annotationElements);
+    }
+    //Updating temporary map for association post processing
+    tempAssociationSetMap.put(associationSet.getAssociationSetFQName().toString(), associationSet);
+    associationSet.setAnnotations(annotation);
+    associationSet.setEdm(edm);
+    return associationSet;
+  }
+
+  private EdmEntitySetImpl readEntitySet(final XMLStreamReader reader) throws XMLStreamException,
+  EntityProviderException, EdmException {
+    reader.require(XMLStreamConstants.START_ELEMENT, edmNamespace, XmlMetadataConstants.EDM_ENTITY_SET);
+    EdmEntitySetImpl entitySet = new EdmEntitySetImpl();
+    EdmAnnotationsImpl annotations = new EdmAnnotationsImpl();
+    List<EdmAnnotationElement> annotationElements = new ArrayList<EdmAnnotationElement>();
+    entitySet.setName(reader.getAttributeValue(null, XmlMetadataConstants.EDM_NAME));
+    String entityType = reader.getAttributeValue(null, XmlMetadataConstants.EDM_ENTITY_TYPE);
+    if (entityType != null) {
+      FullQualifiedName fqName = extractFQName(entityType);
+      entitySet.setEdmEntityTypeName(fqName);
+    } else {
+      throw new EntityProviderException(EntityProviderException.MISSING_ATTRIBUTE
+          .addContent(XmlMetadataConstants.EDM_ENTITY_TYPE).addContent(XmlMetadataConstants.EDM_ENTITY_SET));
+    }
+    annotations.setAnnotationAttributes(readAnnotationAttribute(reader));
+    while (reader.hasNext()
+        && !(reader.isEndElement() && edmNamespace.equals(reader.getNamespaceURI())
+            && XmlMetadataConstants.EDM_ENTITY_SET.equals(reader.getLocalName()))) {
+      reader.next();
+      if (reader.isStartElement()) {
+        extractNamespaces(reader);
+        annotationElements.add(readAnnotationElement(reader));
+      }
+    }
+    if (!annotationElements.isEmpty()) {
+      annotations.setAnnotationElements(annotationElements);
+    }
+    entitySet.setAnnotations(annotations);
+    return entitySet;
+  }
+
+  private EdmAssociation readAssociation(final XMLStreamReader reader, EdmImpl edm)
+      throws XMLStreamException, EntityProviderException, EdmException {
+    reader.require(XMLStreamConstants.START_ELEMENT, edmNamespace, XmlMetadataConstants.EDM_ASSOCIATION);
+
+    EdmAssociationImpl association = new EdmAssociationImpl();
+    association.setName(reader.getAttributeValue(null, XmlMetadataConstants.EDM_NAME));
+    association.setNamespace(currentNamespace);
+    List<EdmMetadataAssociationEnd> associationEnds = new ArrayList<EdmMetadataAssociationEnd>();
+    List<EdmAnnotationElement> annotationElements = new ArrayList<EdmAnnotationElement>();
+    EdmAnnotationsImpl annotations = new EdmAnnotationsImpl();
+    annotations.setAnnotationAttributes(readAnnotationAttribute(reader));
+    while (reader.hasNext()
+        && !(reader.isEndElement() && edmNamespace.equals(reader.getNamespaceURI())
+            && XmlMetadataConstants.EDM_ASSOCIATION.equals(reader.getLocalName()))) {
+      reader.next();
+      if (reader.isStartElement()) {
+        extractNamespaces(reader);
+        currentHandledStartTagName = reader.getLocalName();
+        if (XmlMetadataConstants.EDM_ASSOCIATION_END.equals(currentHandledStartTagName)) {
+          associationEnds.add(readAssociationEnd(reader, edm));
+        } else if (XmlMetadataConstants.EDM_ASSOCIATION_CONSTRAINT.equals(currentHandledStartTagName)) {
+          association.setReferentialConstraint(readReferentialConstraint(reader));
+        } else {
+          annotationElements.add(readAnnotationElement(reader));
+        }
+      }
+    }
+    if (associationEnds.size() < 2 && associationEnds.size() > 2) {
+      throw new EntityProviderException(EntityProviderException.ILLEGAL_ARGUMENT
+          .addContent("Count of association ends should be 2"));
+    }
+    if (!annotationElements.isEmpty()) {
+      annotations.setAnnotationElements(annotationElements);
+    }
+    association.setAnnotations(annotations);
+    association.setEdm(edm);
+    association.setAssociationEnds(associationEnds);
+    associationsMap.put(new FullQualifiedName(currentNamespace, association.getName()), association);
+    return association;
+  }
+
+  private EdmReferentialConstraint readReferentialConstraint(final XMLStreamReader reader) throws XMLStreamException,
+      EntityProviderException, EdmException {
+    reader.require(XMLStreamConstants.START_ELEMENT, edmNamespace, XmlMetadataConstants.EDM_ASSOCIATION_CONSTRAINT);
+    EdmReferentialConstraintImpl refConstraint = new EdmReferentialConstraintImpl();
+    List<EdmAnnotationElement> annotationElements = new ArrayList<EdmAnnotationElement>();
+    EdmAnnotationsImpl annotations = new EdmAnnotationsImpl();
+    annotations.setAnnotationAttributes(readAnnotationAttribute(reader));
+    while (reader.hasNext()
+        && !(reader.isEndElement() && edmNamespace.equals(reader.getNamespaceURI())
+            && XmlMetadataConstants.EDM_ASSOCIATION_CONSTRAINT.equals(reader.getLocalName()))) {
+      reader.next();
+      if (reader.isStartElement()) {
+        extractNamespaces(reader);
+        currentHandledStartTagName = reader.getLocalName();
+        if (XmlMetadataConstants.EDM_ASSOCIATION_PRINCIPAL.equals(currentHandledStartTagName)) {
+          reader
+              .require(XMLStreamConstants.START_ELEMENT, edmNamespace, XmlMetadataConstants.EDM_ASSOCIATION_PRINCIPAL);
+          refConstraint.setPrincipal(readReferentialConstraintRole(reader));
+        } else if (XmlMetadataConstants.EDM_ASSOCIATION_DEPENDENT.equals(currentHandledStartTagName)) {
+          reader
+              .require(XMLStreamConstants.START_ELEMENT, edmNamespace, XmlMetadataConstants.EDM_ASSOCIATION_DEPENDENT);
+          refConstraint.setDependent(readReferentialConstraintRole(reader));
+        } else {
+          annotationElements.add(readAnnotationElement(reader));
+        }
+      }
+    }
+    if (!annotationElements.isEmpty()) {
+      annotations.setAnnotationElements(annotationElements);
+    }
+    refConstraint.setAnnotations(annotations);
+    return refConstraint;
+  }
+
+  private EdmReferentialConstraintRole readReferentialConstraintRole(final XMLStreamReader reader)
+      throws EntityProviderException, XMLStreamException, EdmException {
+    EdmReferentialConstraintRoleImpl rcRole = new EdmReferentialConstraintRoleImpl();
+    rcRole.setRoleName(reader.getAttributeValue(null, XmlMetadataConstants.EDM_ROLE));
+    List<EdmPropertyImpl> properties = new ArrayList<EdmPropertyImpl>();
+    List<EdmAnnotationElement> annotationElements = new ArrayList<EdmAnnotationElement>();
+    List<String> refNames = new ArrayList<String>();
+    EdmAnnotationsImpl annotations = new EdmAnnotationsImpl();
+    annotations.setAnnotationAttributes(readAnnotationAttribute(reader));
+    while (reader.hasNext() && !(reader.isEndElement() && edmNamespace.equals(reader.getNamespaceURI())
+        && (XmlMetadataConstants.EDM_ASSOCIATION_PRINCIPAL.equals(reader.getLocalName())
+            || XmlMetadataConstants.EDM_ASSOCIATION_DEPENDENT.equals(reader.getLocalName())))) {
+      reader.next();
+      if (reader.isStartElement()) {
+        extractNamespaces(reader);
+        currentHandledStartTagName = reader.getLocalName();
+        if (XmlMetadataConstants.EDM_PROPERTY_REF.equals(currentHandledStartTagName)) {
+          EdmPropertyImpl property = (EdmPropertyImpl) readPropertyRef(reader);
+          properties.add(property );
+          refNames.add(property.getName());
+        } else {
+          annotationElements.add(readAnnotationElement(reader));
+        }
+      }
+    }
+    if (!annotationElements.isEmpty()) {
+      annotations.setAnnotationElements(annotationElements);
+    }
+    rcRole.setProperty(properties);
+    rcRole.setRefNames(refNames);
+    rcRole.setAnnotations(annotations);
+    return rcRole;
+  }
+
+  private EdmComplexType readComplexType(final XMLStreamReader reader, Edm edm)
+      throws XMLStreamException, EntityProviderException, EdmException {
+    reader.require(XMLStreamConstants.START_ELEMENT, edmNamespace, XmlMetadataConstants.EDM_COMPLEX_TYPE);
+
+    EdmComplexTypeImpl complexType = new EdmComplexTypeImpl();
+    complexType.setEdmTypeKind(EdmTypeKind.COMPLEX);
+    List<EdmProperty> properties = new ArrayList<EdmProperty>();
+    List<EdmAnnotationElement> annotationElements = new ArrayList<EdmAnnotationElement>();
+    complexType.setName(reader.getAttributeValue(null, XmlMetadataConstants.EDM_NAME));
+    complexType.setNamespace(currentNamespace);
+    String baseType = reader.getAttributeValue(null, XmlMetadataConstants.EDM_BASE_TYPE);
+    if (baseType != null) {
+      FullQualifiedName fqname = extractFQName(baseType);
+      complexType.setBaseTypeName(fqname);
+      complexBaseTypeMap.put(new FullQualifiedName(complexType.getNamespace(), complexType.getName()), fqname);
+    }
+    if (reader.getAttributeValue(null, XmlMetadataConstants.EDM_TYPE_ABSTRACT) != null) {
+      complexType.setAbstract("true".equalsIgnoreCase(reader.getAttributeValue(null,
+          XmlMetadataConstants.EDM_TYPE_ABSTRACT)));
+    }
+    EdmAnnotationsImpl annotations = new EdmAnnotationsImpl();
+    annotations.setAnnotationAttributes(readAnnotationAttribute(reader));
+    while (reader.hasNext()
+        && !(reader.isEndElement() && edmNamespace.equals(reader.getNamespaceURI())
+            && XmlMetadataConstants.EDM_COMPLEX_TYPE.equals(reader.getLocalName()))) {
+      reader.next();
+      if (reader.isStartElement()) {
+        extractNamespaces(reader);
+        currentHandledStartTagName = reader.getLocalName();
+        if (XmlMetadataConstants.EDM_PROPERTY.equals(currentHandledStartTagName)) {
+          properties.add(readProperty(reader, edm));
+        } else {
+          annotationElements.add(readAnnotationElement(reader));
+        }
+      }
+    }
+    if (!annotationElements.isEmpty()) {
+      annotations.setAnnotationElements(annotationElements);
+    }
+    complexType.setProperties(properties);
+    List<String> edmPropertyNames = new ArrayList<String>();
+    for (EdmProperty name : properties) {
+      edmPropertyNames.add(name.getName());
+    }
+    complexType.setEdmPropertyNames(edmPropertyNames);
+    if (complexType.getName() != null) {
+      FullQualifiedName fqName = new FullQualifiedName(currentNamespace, complexType.getName());
+      complexTypesMap.put(fqName, complexType);
+      if (complexPropertyMap.get(fqName) != null) {// POST processing to set the edm types for complex types
+        ((EdmComplexPropertyImpl) complexPropertyMap.get(fqName)).setEdmType(complexType);
+      }
+    } else {
+      throw new EntityProviderException(EntityProviderException.MISSING_ATTRIBUTE.addContent("Name"));
+    }
+    return complexType;
+
+  }
+
+  private EdmEntityType readEntityType(final XMLStreamReader reader,
+      EdmImpl edm) throws XMLStreamException, EntityProviderException, EdmException {
+    reader.require(XMLStreamConstants.START_ELEMENT, edmNamespace, XmlMetadataConstants.EDM_ENTITY_TYPE);
+    EdmEntityTypeImpl entityType = new EdmEntityTypeImpl();
+    List<EdmProperty> properties = new ArrayList<EdmProperty>();
+    List<String> edmPropertyNames = new ArrayList<String>();
+    List<EdmNavigationProperty> edmNavProperties = new ArrayList<EdmNavigationProperty>();
+    List<EdmAnnotationElement> annotationElements = new ArrayList<EdmAnnotationElement>();
+    List<String> edmNavigationPropertyNames = new ArrayList<String>();
+    List<String> edmKeyPropertyNames = new ArrayList<String>();
+    List<EdmProperty> edmKeyProperties = new ArrayList<EdmProperty>();
+    EdmKeyImpl key = null;
+    ((EdmNamedImpl) entityType).setName(reader.getAttributeValue(null, XmlMetadataConstants.EDM_NAME));
+    entityType.setNamespace(currentNamespace);
+    entityType.setEdm((EdmImpl) edm);
+    String hasStream = reader.getAttributeValue(Edm.NAMESPACE_M_2007_08, XmlMetadataConstants.M_ENTITY_TYPE_HAS_STREAM);
+    if (hasStream != null) {
+      entityType.setHasStream("true".equalsIgnoreCase(hasStream));
+    }
+
+    if (reader.getAttributeValue(null, XmlMetadataConstants.EDM_TYPE_ABSTRACT) != null) {
+      entityType.setAbstract("true".equalsIgnoreCase(reader.getAttributeValue(null,
+          XmlMetadataConstants.EDM_TYPE_ABSTRACT)));
+    }
+    String baseType = reader.getAttributeValue(null, XmlMetadataConstants.EDM_BASE_TYPE);
+    if (baseType != null) {
+      FullQualifiedName fqName = extractFQName(baseType);
+      entityType.setBaseType(fqName);
+      //Populating base type map with child and parent for multiple inheritance
+      entityBaseTypeMap.put(extractFQNameFromEntityType(entityType), fqName);
+    }
+    entityType.setCustomizableFeedMappings(readCustomizableFeedMappings(reader));
+    EdmAnnotationsImpl annotations = new EdmAnnotationsImpl();
+    annotations.setAnnotationAttributes(readAnnotationAttribute(reader));
+    while (reader.hasNext()
+        && !(reader.isEndElement() && edmNamespace.equals(reader.getNamespaceURI())
+            && XmlMetadataConstants.EDM_ENTITY_TYPE.equals(reader.getLocalName()))) {
+      reader.next();
+      if (reader.isStartElement()) {
+        currentHandledStartTagName = reader.getLocalName();
+        if (XmlMetadataConstants.EDM_ENTITY_TYPE_KEY.equals(currentHandledStartTagName)) {
+          key = readEntityTypeKey(reader);
+        } else if (XmlMetadataConstants.EDM_PROPERTY.equals(currentHandledStartTagName)) {
+          properties.add(readProperty(reader, edm));
+        } else if (XmlMetadataConstants.EDM_NAVIGATION_PROPERTY.equals(currentHandledStartTagName)) {
+          edmNavProperties.add(readNavigationProperty(reader, edm));
+        } else {
+          annotationElements.add(readAnnotationElement(reader));
+        }
+        extractNamespaces(reader);
+      }
+    }
+    if (!annotationElements.isEmpty()) {
+      annotations.setAnnotationElements(annotationElements);
+    }
+    
+    for (EdmProperty property : properties) {
+      edmPropertyNames.add(property.getName());
+      if (key != null) {        
+        for(EdmProperty keyProperty: key.getKeys()){
+          if(property.getName().equals(keyProperty.getName())){
+            edmKeyPropertyNames.add(keyProperty.getName());
+            edmKeyProperties.add(property);
+          }
+        }
+      }
+    }
+    for ( EdmNavigationProperty navigations : edmNavProperties){
+      edmNavigationPropertyNames.add(navigations.getName());
+    }
+
+    entityType.setAnnotations(annotations);
+    entityType.setEdmKeyProperties(edmKeyProperties);
+    entityType.setNavigationProperties(edmNavProperties);
+    entityType.setEdmNavigationPropertyNames(edmNavigationPropertyNames);    
+    entityType.setEdmKeyPropertyNames(edmKeyPropertyNames);
+    entityType.setProperties(properties);
+    entityType.setEdmPropertyNames(edmPropertyNames);
+    if (entityType.getName() != null) {
+      FullQualifiedName fqName = new FullQualifiedName(currentNamespace, entityType.getName());
+      entityTypesMap.put(fqName, entityType);
+    } else {
+      throw new EntityProviderException(EntityProviderException.MISSING_ATTRIBUTE.addContent("Name"));
+    }
+
+    return entityType;
+  }
+
+  private EdmKeyImpl readEntityTypeKey(final XMLStreamReader reader) throws XMLStreamException,
+  EntityProviderException, EdmException {
+    reader.require(XMLStreamConstants.START_ELEMENT, edmNamespace, XmlMetadataConstants.EDM_ENTITY_TYPE_KEY);
+    List<EdmProperty> keys = new ArrayList<EdmProperty>();
+    List<EdmAnnotationElement> annotationElements = new ArrayList<EdmAnnotationElement>();
+    List<EdmAnnotationAttribute> annotationAttributes = readAnnotationAttribute(reader);
+    while (reader.hasNext()
+        && !(reader.isEndElement() && edmNamespace.equals(reader.getNamespaceURI())
+            && XmlMetadataConstants.EDM_ENTITY_TYPE_KEY.equals(reader.getLocalName()))) {
+      reader.next();
+      if (reader.isStartElement()) {
+        extractNamespaces(reader);
+        currentHandledStartTagName = reader.getLocalName();
+        if (XmlMetadataConstants.EDM_PROPERTY_REF.equals(currentHandledStartTagName)) {
+          reader.require(XMLStreamConstants.START_ELEMENT, edmNamespace, XmlMetadataConstants.EDM_PROPERTY_REF);
+          keys.add(readPropertyRef(reader));
+        } else {
+          annotationElements.add(readAnnotationElement(reader));
+        }
+      }
+    }
+    EdmKeyImpl key = new EdmKeyImpl().setKeys(keys).setAnnotationAttributes(annotationAttributes);
+    if (!annotationElements.isEmpty()) {
+      key.setAnnotationElements(annotationElements);
+    }
+    return key;
+  }
+
+  private EdmProperty readPropertyRef(final XMLStreamReader reader) throws XMLStreamException, 
+  EntityProviderException, EdmException {
+    reader.require(XMLStreamConstants.START_ELEMENT, edmNamespace, XmlMetadataConstants.EDM_PROPERTY_REF);
+    EdmPropertyImpl propertyRef = new EdmPropertyRefImpl();
+    propertyRef.setName(reader.getAttributeValue(null, XmlMetadataConstants.EDM_NAME));
+    EdmAnnotations annotations = new EdmAnnotationsImpl();
+    List<EdmAnnotationElement> annotationElements = new ArrayList<EdmAnnotationElement>();
+    ((EdmAnnotationsImpl) annotations).setAnnotationAttributes(readAnnotationAttribute(reader));
+    while (reader.hasNext() && !(reader.isEndElement() && edmNamespace.equals(reader.getNamespaceURI())
+        && XmlMetadataConstants.EDM_PROPERTY_REF.equals(reader.getLocalName()))) {
+      reader.next();
+      if (reader.isStartElement()) {
+        extractNamespaces(reader);
+        annotationElements.add(readAnnotationElement(reader));
+      }
+    }
+    if (!annotationElements.isEmpty()) {
+      ((EdmAnnotationsImpl) annotations).setAnnotationElements(annotationElements);
+    }
+    propertyRef.setAnnotations(annotations);
+    return propertyRef;
+  }
+
+  private EdmNavigationProperty readNavigationProperty(final XMLStreamReader reader, EdmImpl edm) 
+      throws XMLStreamException, EntityProviderException, EdmException {
+    reader.require(XMLStreamConstants.START_ELEMENT, edmNamespace, XmlMetadataConstants.EDM_NAVIGATION_PROPERTY);
+
+    EdmNavigationPropertyImpl navProperty = new EdmNavigationPropertyImpl();
+    List<EdmAnnotationElement> annotationElements = new ArrayList<EdmAnnotationElement>();
+    navProperty.setName(reader.getAttributeValue(null, XmlMetadataConstants.EDM_NAME));
+    String relationship = reader.getAttributeValue(null, XmlMetadataConstants.EDM_NAVIGATION_RELATIONSHIP);
+    if (relationship != null) {
+      FullQualifiedName fqName = extractFQName(relationship);
+      navProperty.setRelationshipName(fqName);
+
+    } else {
+      throw new EntityProviderException(EntityProviderException.MISSING_ATTRIBUTE
+          .addContent(XmlMetadataConstants.EDM_NAVIGATION_RELATIONSHIP).addContent(
+              XmlMetadataConstants.EDM_NAVIGATION_PROPERTY));
+    }
+
+    navProperty.setFromRole(reader.getAttributeValue(null, XmlMetadataConstants.EDM_NAVIGATION_FROM_ROLE));
+    navProperty.setToRole(reader.getAttributeValue(null, XmlMetadataConstants.EDM_NAVIGATION_TO_ROLE));
+    EdmAnnotations annotations = new EdmAnnotationsImpl();
+    ((EdmAnnotationsImpl) annotations).setAnnotationAttributes(readAnnotationAttribute(reader));
+    while (reader.hasNext() && !(reader.isEndElement() && edmNamespace.equals(reader.getNamespaceURI())
+        && XmlMetadataConstants.EDM_NAVIGATION_PROPERTY.equals(reader.getLocalName()))) {
+      reader.next();
+      if (reader.isStartElement()) {
+        extractNamespaces(reader);
+        annotationElements.add(readAnnotationElement(reader));
+      }
+    }
+    if (!annotationElements.isEmpty()) {
+      ((EdmAnnotationsImpl) annotations).setAnnotationElements(annotationElements);
+    }
+    navProperty.setAnnotations(annotations);
+    navProperty.setEdm(edm);        
+    navProperties.add(navProperty);
+    return navProperty;
+  }
+
+  private EdmProperty readProperty(final XMLStreamReader reader, Edm edm)
+      throws XMLStreamException, EntityProviderException, EdmException {
+    reader.require(XMLStreamConstants.START_ELEMENT, edmNamespace, XmlMetadataConstants.EDM_PROPERTY);
+    EdmPropertyImpl property;
+    List<EdmAnnotationElement> annotationElements = new ArrayList<EdmAnnotationElement>();
+    String type = reader.getAttributeValue(null, XmlMetadataConstants.EDM_TYPE);
+    if (type == null) {
+      throw new EntityProviderException(EntityProviderException.MISSING_ATTRIBUTE
+          .addContent(XmlMetadataConstants.EDM_TYPE).addContent(XmlMetadataConstants.EDM_PROPERTY));
+    }
+    FullQualifiedName fqName = extractFQName(type);
+
+    if (EdmSimpleType.EDM_NAMESPACE.equals(fqName.getNamespace())) {
+      property = readSimpleProperty(reader, fqName);
+    } else {
+      property = readComplexProperty(reader, fqName, edm);
+    }
+    property.setFacets(readFacets(reader));
+    property.setCustomizableFeedMappings(readCustomizableFeedMappings(reader));
+    property.setMimeType(reader.getAttributeValue(Edm.NAMESPACE_M_2007_08, XmlMetadataConstants.M_MIMETYPE));
+    EdmAnnotations annotations = new EdmAnnotationsImpl();
+    ((EdmAnnotationsImpl) annotations).setAnnotationAttributes(readAnnotationAttribute(reader));
+    while (reader.hasNext() && !(reader.isEndElement() && edmNamespace.equals(reader.getNamespaceURI())
+        && XmlMetadataConstants.EDM_PROPERTY.equals(reader.getLocalName()))) {
+      reader.next();
+      if (reader.isStartElement()) {
+        extractNamespaces(reader);
+        annotationElements.add(readAnnotationElement(reader));
+      }
+    }
+    if (!annotationElements.isEmpty()) {
+      ((EdmAnnotationsImpl) annotations).setAnnotationElements(annotationElements);
+    }
+    property.setAnnotations(annotations);
+    return property;
+  }
+
+  private EdmPropertyImpl readComplexProperty(final XMLStreamReader reader, final FullQualifiedName fqName, Edm edm)
+      throws XMLStreamException, EdmException {
+    EdmComplexPropertyImpl property = new EdmComplexPropertyImpl();
+    property.setName(reader.getAttributeValue(null, XmlMetadataConstants.EDM_NAME));
+    property.setTypeName(fqName);
+    property.setEdm((EdmImpl) edm);
+    complexPropertyMap.put(fqName, property);
+    return property;
+  }
+
+  private EdmPropertyImpl readSimpleProperty(final XMLStreamReader reader, final FullQualifiedName fqName)
+      throws XMLStreamException, EdmException {
+    EdmSimplePropertyImpl property = new EdmSimplePropertyImpl();
+    property.setName(reader.getAttributeValue(null, XmlMetadataConstants.EDM_NAME));
+    property.setTypeName(fqName);
+    property.setSimpleType(EdmSimpleTypeKind.valueOf(fqName.getName()));
+    property.setEdmType(EdmSimpleTypeFacadeImpl.getEdmSimpleType(property.getSimpleType()));
+    return property;
+  }
+
+  private EdmFacets readFacets(final XMLStreamReader reader) throws XMLStreamException {
+    String isNullable = reader.getAttributeValue(null, XmlMetadataConstants.EDM_PROPERTY_NULLABLE);
+    String maxLength = reader.getAttributeValue(null, XmlMetadataConstants.EDM_PROPERTY_MAX_LENGTH);
+    String precision = reader.getAttributeValue(null, XmlMetadataConstants.EDM_PROPERTY_PRECISION);
+    String scale = reader.getAttributeValue(null, XmlMetadataConstants.EDM_PROPERTY_SCALE);
+    String isFixedLength = reader.getAttributeValue(null, XmlMetadataConstants.EDM_PROPERTY_FIXED_LENGTH);
+    String isUnicode = reader.getAttributeValue(null, XmlMetadataConstants.EDM_PROPERTY_UNICODE);
+    String concurrencyMode = reader.getAttributeValue(null, XmlMetadataConstants.EDM_PROPERTY_CONCURRENCY_MODE);
+    String defaultValue = reader.getAttributeValue(null, XmlMetadataConstants.EDM_PROPERTY_DEFAULT_VALUE);
+    String collation = reader.getAttributeValue(null, XmlMetadataConstants.EDM_PROPERTY_COLLATION);
+    if (isNullable != null || maxLength != null || precision != null || scale != null || isFixedLength != null
+        || isUnicode != null || concurrencyMode != null || defaultValue != null || collation != null) {
+      EdmFacets facets = new Facets();
+      if (isNullable != null) {
+        ((Facets) facets).setNullable("true".equalsIgnoreCase(isNullable));
+      }
+      if (maxLength != null) {
+        if (XmlMetadataConstants.EDM_PROPERTY_MAX_LENGTH_MAX_VALUE_FIRST_UPPERCASE.equals(maxLength)
+            || XmlMetadataConstants.EDM_PROPERTY_MAX_LENGTH_MAX_VALUE_LOWERCASE.equals(maxLength)) {
+          ((Facets) facets).setMaxLength(Integer.MAX_VALUE);
+        } else {
+          ((Facets) facets).setMaxLength(Integer.parseInt(maxLength));
+        }
+      }
+      if (precision != null) {
+        ((Facets) facets).setPrecision(Integer.parseInt(precision));
+      }
+      if (scale != null) {
+        ((Facets) facets).setScale(Integer.parseInt(scale));
+      }
+      if (isFixedLength != null) {
+        ((Facets) facets).setFixedLength("true".equalsIgnoreCase(isFixedLength));
+      }
+      if (isUnicode != null) {
+        ((Facets) facets).setUnicode("true".equalsIgnoreCase(isUnicode));
+      }
+      for (int i = 0; i < EdmConcurrencyMode.values().length; i++) {
+        if (EdmConcurrencyMode.values()[i].name().equalsIgnoreCase(concurrencyMode)) {
+          ((Facets) facets).setConcurrencyMode(EdmConcurrencyMode.values()[i]);
+        }
+      }
+      ((Facets) facets).setDefaultValue(defaultValue);
+      ((Facets) facets).setCollation(collation);
+      return facets;
+    } else {
+      return null;
+    }
+  }
+
+  private EdmCustomizableFeedMappings readCustomizableFeedMappings(final XMLStreamReader reader) {
+    String targetPath = reader.getAttributeValue(Edm.NAMESPACE_M_2007_08, XmlMetadataConstants.M_FC_TARGET_PATH);
+    String sourcePath = reader.getAttributeValue(Edm.NAMESPACE_M_2007_08, XmlMetadataConstants.M_FC_SOURCE_PATH);
+    String nsUri = reader.getAttributeValue(Edm.NAMESPACE_M_2007_08, XmlMetadataConstants.M_FC_NS_URI);
+    String nsPrefix = reader.getAttributeValue(Edm.NAMESPACE_M_2007_08, XmlMetadataConstants.M_FC_PREFIX);
+    String keepInContent = reader.getAttributeValue(Edm.NAMESPACE_M_2007_08, XmlMetadataConstants.M_FC_KEEP_IN_CONTENT);
+    String contentKind = reader.getAttributeValue(Edm.NAMESPACE_M_2007_08, XmlMetadataConstants.M_FC_CONTENT_KIND);
+
+    if (targetPath != null || sourcePath != null || nsUri != null || nsPrefix != null || keepInContent != null
+        || contentKind != null) {
+      EdmCustomizableFeedMappings feedMapping = new EdmCustomizableFeedMappingsImpl();
+      EdmCustomizableFeedMappingsImpl feedMappingImpl = (EdmCustomizableFeedMappingsImpl) feedMapping;
+      if (keepInContent != null) {
+        feedMappingImpl.setFcKeepInContent("true".equals(keepInContent));
+      }
+      for (int i = 0; i < EdmContentKind.values().length; i++) {
+        if (EdmContentKind.values()[i].name().equalsIgnoreCase(contentKind)) {
+          feedMappingImpl.setFcContentKind(EdmContentKind.values()[i]);
+        }
+      }
+      feedMappingImpl.setFcTargetPath(targetPath).setFcSourcePath(sourcePath).setFcNsUri(nsUri).setFcNsPrefix(nsPrefix);
+      return feedMapping;
+    } else {
+      return null;
+    }
+
+  }
+
+  private EdmMetadataAssociationEnd readAssociationEnd(final XMLStreamReader reader, 
+      EdmImpl edm) throws EntityProviderException, XMLStreamException {
+    reader.require(XMLStreamConstants.START_ELEMENT, edmNamespace, XmlMetadataConstants.EDM_ASSOCIATION_END);
+
+    EdmAssociationEndImpl associationEnd = new EdmAssociationEndImpl();
+    EdmAnnotationsImpl annotations = new EdmAnnotationsImpl();
+    List<EdmAnnotationElement> annotationElements = new ArrayList<EdmAnnotationElement>();
+    associationEnd.setRole(reader.getAttributeValue(null, XmlMetadataConstants.EDM_ROLE));
+    associationEnd.setMultiplicity(EdmMultiplicity.fromLiteral(reader.getAttributeValue(null,
+        XmlMetadataConstants.EDM_ASSOCIATION_MULTIPLICITY)));
+    String type = reader.getAttributeValue(null, XmlMetadataConstants.EDM_TYPE);
+    if (type == null) {
+      throw new EntityProviderException(EntityProviderException.MISSING_ATTRIBUTE
+          .addContent(XmlMetadataConstants.EDM_TYPE).addContent(XmlMetadataConstants.EDM_ASSOCIATION_END));
+    }
+    associationEnd.setEdm(edm);
+    associationEnd.setType(extractFQName(type));
+    annotations.setAnnotationAttributes(readAnnotationAttribute(reader));
+    while (reader.hasNext() && !(reader.isEndElement() && edmNamespace.equals(reader.getNamespaceURI())
+        && XmlMetadataConstants.EDM_ASSOCIATION_END.equals(reader.getLocalName()))) {
+      reader.next();
+      if (reader.isStartElement()) {
+        extractNamespaces(reader);
+        currentHandledStartTagName = reader.getLocalName();
+        if (XmlMetadataConstants.EDM_ASSOCIATION_ONDELETE.equals(currentHandledStartTagName)) {
+          EdmOnDeleteImpl onDelete = new EdmOnDeleteImpl();
+          for (int i = 0; i < EdmAction.values().length; i++) {
+            if (EdmAction.values()[i].name().equalsIgnoreCase(
+                reader.getAttributeValue(null, XmlMetadataConstants.EDM_ONDELETE_ACTION))) {
+              onDelete.setAction(EdmAction.values()[i]);
+            }
+          }
+          associationEnd.setOnDelete(onDelete);
+        } else {
+          annotationElements.add(readAnnotationElement(reader));
+        }
+      }
+    }
+    if (!annotationElements.isEmpty()) {
+      annotations.setAnnotationElements(annotationElements);
+    }
+    associationEnd.setAnnotations(annotations);
+    return associationEnd;
+  }
+
+  private EdmAnnotationElement readAnnotationElement(final XMLStreamReader reader) throws XMLStreamException {
+    EdmAnnotationElementImpl elementImpl = new EdmAnnotationElementImpl();
+    List<EdmAnnotationElement> annotationElements = new ArrayList<EdmAnnotationElement>();
+    List<EdmAnnotationAttribute> annotationAttributes = new ArrayList<EdmAnnotationAttribute>();
+    elementImpl.setName(reader.getLocalName());
+    String elementNamespace = reader.getNamespaceURI();
+    if (!edmNamespaces.contains(elementNamespace)) {
+      elementImpl.setPrefix(reader.getPrefix());
+      elementImpl.setNamespace(elementNamespace);
+    }
+    for (int i = 0; i < reader.getAttributeCount(); i++) {
+      EdmAnnotationAttributeImpl annotationAttribute = new EdmAnnotationAttributeImpl();
+      annotationAttribute.setText(reader.getAttributeValue(i));
+      annotationAttribute.setName(reader.getAttributeLocalName(i));
+      annotationAttribute.setPrefix(reader.getAttributePrefix(i));
+      String namespace = reader.getAttributeNamespace(i);
+      if (namespace != null && !isDefaultNamespace(namespace)) {
+        annotationAttribute.setNamespace(namespace);
+      }
+      annotationAttributes.add(annotationAttribute);
+    }
+    if (!annotationAttributes.isEmpty()) {
+      elementImpl.setAttributes(annotationAttributes);
+    }
+
+    boolean justRead = false;
+    if (reader.hasNext()) {
+      reader.next();
+      justRead = true;
+    }
+
+    while (justRead && !(reader.isEndElement() && elementImpl.getName() != null
+        && elementImpl.getName().equals(reader.getLocalName()))) {
+      justRead = false;
+      if (reader.isStartElement()) {
+        annotationElements.add(readAnnotationElement(reader));
+        if (reader.hasNext()) {
+          reader.next();
+          justRead = true;
+        }
+      } else if (reader.isCharacters()) {
+        String elementText = "";
+        do {
+          justRead = false;
+          elementText = elementText + reader.getText();
+          if (reader.hasNext()) {
+            reader.next();
+            justRead = true;
+          }
+        } while (justRead && reader.isCharacters());
+        elementImpl.setText(elementText);
+      }
+    }
+    if (!annotationElements.isEmpty()) {
+      elementImpl.setChildElements(annotationElements);
+    }
+    return elementImpl;
+  }
+
+  private List<EdmAnnotationAttribute> readAnnotationAttribute(final XMLStreamReader reader) {
+    List<EdmAnnotationAttribute> annotationAttributes = new ArrayList<EdmAnnotationAttribute>();
+    for (int i = 0; i < reader.getAttributeCount(); i++) {
+      String attributeNamespace = reader.getAttributeNamespace(i);
+      if (attributeNamespace != null && !isDefaultNamespace(attributeNamespace)
+          && !mandatoryNamespaces.containsValue(attributeNamespace)
+          && !edmNamespaces.contains(attributeNamespace)) {
+        annotationAttributes.add(new EdmAnnotationAttributeImpl().setName(reader.getAttributeLocalName(i)).setPrefix(
+            reader.getAttributePrefix(i)).setNamespace(attributeNamespace).setText(
+                reader.getAttributeValue(i)));
+      }
+    }
+    if (annotationAttributes.isEmpty()) {
+      return null;
+    }
+    return annotationAttributes;
+  }
+
+  private boolean isDefaultNamespace(final String namespace) {
+    return namespace.isEmpty();
+  }
+
+  private void checkMandatoryNamespacesAvailable() throws EntityProviderException {
+    if (!xmlNamespaceMap.containsValue(Edm.NAMESPACE_EDMX_2007_06)) {
+      throw new EntityProviderException(EntityProviderException.INVALID_NAMESPACE
+          .addContent(Edm.NAMESPACE_EDMX_2007_06));
+    } else if (!xmlNamespaceMap.containsValue(Edm.NAMESPACE_M_2007_08)) {
+      throw new EntityProviderException(EntityProviderException.INVALID_NAMESPACE.addContent(Edm.NAMESPACE_M_2007_08));
+    }
+  }
+
+  private void checkEdmNamespace() throws EntityProviderException {
+    if (!edmNamespaces.contains(edmNamespace)) {
+      throw new EntityProviderException(EntityProviderException.INVALID_NAMESPACE
+          .addContent(XmlMetadataConstants.EDM_SCHEMA));
+    }
+  }
+
+  private void extractNamespaces(final XMLStreamReader reader) throws EntityProviderException {
+    int namespaceCount = reader.getNamespaceCount();
+    for (int i = 0; i < namespaceCount; i++) {
+      String namespacePrefix = reader.getNamespacePrefix(i);
+      String namespaceUri = reader.getNamespaceURI(i);
+      if (namespacePrefix == null || isDefaultNamespace(namespacePrefix)) {
+        namespacePrefix = Edm.PREFIX_EDM;
+      }
+      //Ignoring the duplicate tags, parent tag namespace takes precedence
+      if (!xmlNamespaceMap.containsKey(namespacePrefix)) {
+        xmlNamespaceMap.put(namespacePrefix, namespaceUri);
+      }
+    }
+  }
+
+  private FullQualifiedName extractFQName(final String name)
+      throws EntityProviderException {
+    // Looking for the last dot
+    String[] names = name.split("\\" + Edm.DELIMITER + "(?=[^\\" + Edm.DELIMITER + "]+$)");
+    if (names.length != 2) {
+      throw new EntityProviderException(EntityProviderException.ILLEGAL_ARGUMENT
+          .addContent("Attribute should specify a namespace qualified name or an alias qualified name"));
+    } else {
+      return new FullQualifiedName(names[0], names[1]);
+    }
+  }
+
+  private FullQualifiedName extractFQNameFromEntityType(final EdmEntityType entity)
+      throws EntityProviderException, EdmException {
+    return new FullQualifiedName(entity.getNamespace(), entity.getName());
+  }
+
+  private FullQualifiedName validateEntityTypeWithAlias(final FullQualifiedName aliasName)
+      throws EntityProviderException {
+    String namespace = aliasNamespaceMap.get(aliasName.getNamespace());
+    FullQualifiedName fqName = new FullQualifiedName(namespace, aliasName.getName());
+    if (!entityTypesMap.containsKey(fqName)) {
+      throw new EntityProviderException(EntityProviderException.ILLEGAL_ARGUMENT.addContent("Invalid Type"));
+    }
+    return fqName;
+  }
+
+  private void validateEntityTypes() throws EntityProviderException, EdmException {
+    for (Map.Entry<FullQualifiedName, EdmEntityType> entityTypes : entityTypesMap.entrySet()) {
+      if (entityTypes.getValue() != null && entityTypes.getKey() != null) {
+        EdmEntityTypeImpl entityType = (EdmEntityTypeImpl) entityTypes.getValue();
+        if (entityType.getBaseTypeName() != null) {
+          FullQualifiedName baseTypeFQName = entityType.getBaseTypeName();
+          EdmEntityType baseEntityType;
+          if (!entityTypesMap.containsKey(baseTypeFQName)) {
+            FullQualifiedName fqName = validateEntityTypeWithAlias(baseTypeFQName);
+            baseEntityType = entityTypesMap.get(fqName);
+          } else {
+            baseEntityType = fetchLastBaseType(baseTypeFQName, entityTypesMap);
+          }
+          if (baseEntityType != null && 
+              (baseEntityType.getKeyProperties() == null || baseEntityType.getKeyProperties().isEmpty())) {
+            throw new EntityProviderException(EntityProviderException.ILLEGAL_ARGUMENT
+                .addContent("Missing key for EntityType " + baseEntityType.getName()));
+          }
+        } else if (entityType.getKeyProperties() == null || entityType.getKeyProperties().isEmpty()) {
+          throw new EntityProviderException(EntityProviderException.ILLEGAL_ARGUMENT
+              .addContent("Missing key for EntityType " + entityType.getName()));
+        }
+      }
+    }
+  }
+
+  /*
+   * This method gets the last base type of the EntityType
+   * which has key defined in order to validate it
+   */
+  private EdmEntityType fetchLastBaseType(FullQualifiedName baseTypeFQName,
+      Map<FullQualifiedName, EdmEntityType> entityTypesMap2)
+      throws EntityProviderException, EdmException {
+
+    EdmEntityTypeImpl baseEntityType = null;
+    while (baseTypeFQName != null) {
+      baseEntityType = (EdmEntityTypeImpl) entityTypesMap2.get(baseTypeFQName);
+      if(baseEntityType != null){
+        if (baseEntityType.getKeyPropertyNames() != null && !baseEntityType.getKeyPropertyNames().isEmpty()) {
+          break;
+        } else if (baseEntityType.getBaseType() != null) {
+          baseTypeFQName = baseEntityType.getBaseTypeName();
+        } else if (baseEntityType.getBaseType() == null) {
+          break;
+        }
+      }
+    }
+    return baseEntityType;
+  }
+
+  private FullQualifiedName validateComplexTypeWithAlias(final FullQualifiedName aliasName)
+      throws EntityProviderException {
+    String namespace = aliasNamespaceMap.get(aliasName.getNamespace());
+    FullQualifiedName fqName = new FullQualifiedName(namespace, aliasName.getName());
+    if (!complexTypesMap.containsKey(fqName)) {
+      throw new EntityProviderException(EntityProviderException.ILLEGAL_ARGUMENT.addContent("Invalid BaseType")
+          .addContent(fqName));
+    }
+    return fqName;
+  }
+
+  private void validateComplexTypes() throws EntityProviderException, EdmException {
+    for (Map.Entry<FullQualifiedName, EdmComplexType> complexTypes : complexTypesMap.entrySet()) {
+      if (complexTypes.getValue() != null && complexTypes.getKey() != null) {
+        EdmComplexTypeImpl complexType = (EdmComplexTypeImpl) complexTypes.getValue();
+        if (complexType.getBaseType() != null) {
+          FullQualifiedName baseTypeFQName = complexType.getEdmBaseTypeName();
+          if (!complexTypesMap.containsKey(baseTypeFQName)) {
+            validateComplexTypeWithAlias(baseTypeFQName);
+          }
+        }
+      }
+    }
+  }
+
+  private void validateRelationship() throws EntityProviderException, EdmException {
+    for (EdmNavigationProperty navProperty : navProperties) {
+      EdmNavigationPropertyImpl navigationImpl = (EdmNavigationPropertyImpl) navProperty;
+      if (associationsMap.containsKey(navigationImpl.getRelationshipName())) {
+        EdmAssociationImpl assoc = (EdmAssociationImpl) associationsMap.get(navigationImpl.getRelationshipName());
+        if (!(assoc.getEnd1().getRole().equals(navProperty.getFromRole())
+            ^ assoc.getEnd1().getRole().equals(navProperty.getToRole())
+            && (assoc.getEnd2().getRole().equals(navProperty.getFromRole()) ^ assoc.getEnd2().getRole().equals(
+                navProperty.getToRole())))) {
+          throw new EntityProviderException(EntityProviderException.ILLEGAL_ARGUMENT
+              .addContent("Invalid end of association"));
+        }
+        if (!entityTypesMap.containsKey(extractFQNameFromEntityType(assoc.getEnd1().getEntityType()))) {
+          EdmEntityType entityType = assoc.getEnd1().getEntityType();
+          validateEntityTypeWithAlias(extractFQNameFromEntityType(entityType));
+        }
+        if (!entityTypesMap.containsKey(extractFQNameFromEntityType(assoc.getEnd2().getEntityType()))) {
+          EdmEntityType entityType = assoc.getEnd2().getEntityType();
+          validateEntityTypeWithAlias(extractFQNameFromEntityType(entityType));
+        }
+      } else {
+        throw new EntityProviderException(EntityProviderException.ILLEGAL_ARGUMENT.addContent("Invalid Relationship"));
+      }
+    }
+
+  }
+
+  private void validateAssociation() throws EntityProviderException, EdmException {
+    for (Map.Entry<FullQualifiedName, EdmEntityContainer> container : containerMap.entrySet()) {
+      for (EdmAssociationSet associationSet : container.getValue().getAssociationSets()) {
+        FullQualifiedName association = new FullQualifiedName(associationSet.getAssociation().getNamespace(),
+            associationSet.getAssociation().getName());
+        if (associationsMap.containsKey(association)) {
+          validateAssociationEnd(((EdmAssociationSetImpl) associationSet).getEnd1(), associationsMap.get(association));
+          validateAssociationEnd(((EdmAssociationSetImpl) associationSet).getEnd2(), associationsMap.get(association));
+          boolean end1 = false;
+          boolean end2 = false;
+          for (EdmEntitySet entitySet : container.getValue().getEntitySets()) {
+            EdmAssociationSetEnd associationSetEnd1 = ((EdmAssociationSetImpl) associationSet).getEnd1();
+            if (entitySet.getName().equals(((EdmAssociationSetEndImpl) associationSetEnd1).getEntitySetName())) {
+              end1 = true;
+            }
+            EdmAssociationSetEnd associationSetEnd2 = ((EdmAssociationSetImpl) associationSet).getEnd2();
+            if (entitySet.getName().equals(((EdmAssociationSetEndImpl) associationSetEnd2).getEntitySetName())) {
+              end2 = true;
+            }
+          }
+          if (!(end1 && end2)) {
+            throw new EntityProviderException(EntityProviderException.ILLEGAL_ARGUMENT
+                .addContent("Invalid AssociationSet"));
+          }
+        } else {
+          throw new EntityProviderException(EntityProviderException.ILLEGAL_ARGUMENT
+              .addContent("Invalid AssociationSet"));
+        }
+      }
+    }
+
+  }
+
+  private void validateAssociationEnd(final EdmAssociationSetEnd end, final EdmAssociation association)
+      throws EntityProviderException, EdmException {
+    if (!(association.getEnd1().getRole().equals(end.getRole()) ^ association
+        .getEnd2().getRole().equals(end.getRole()))) {
+      throw new EntityProviderException(EntityProviderException.COMMON.addContent("Invalid Association"));
+    }
+  }
+
+  private void validateEntitySet() throws EntityProviderException, EdmException {
+    for (Map.Entry<FullQualifiedName, EdmEntityContainer> container : containerMap.entrySet()) {
+      for (EdmEntitySet entitySet : container.getValue().getEntitySets()) {
+        FullQualifiedName entityType = extractFQNameFromEntityType(entitySet.getEntityType());
+        if (!(entityTypesMap.containsKey(entityType))) {
+          validateEntityTypeWithAlias(entityType);
+        }
+      }
+    }
+  }
+
+  private void validate() throws EntityProviderException, EdmException {
+    checkMandatoryNamespacesAvailable();
+    validateEntityTypes();
+    validateComplexTypes();
+    validateRelationship();
+    validateEntitySet();
+    validateAssociation();
+  }
+
+  private void initialize() {
+    xmlNamespaceMap = new HashMap<String, String>();
+    mandatoryNamespaces = new HashMap<String, String>();
+    mandatoryNamespaces.put(Edm.PREFIX_EDMX, Edm.NAMESPACE_EDMX_2007_06);
+    mandatoryNamespaces.put(Edm.PREFIX_M, Edm.NAMESPACE_M_2007_08);
+    edmNamespaces = new HashSet<String>();
+    edmNamespaces.add(Edm.NAMESPACE_EDM_2006_04);
+    edmNamespaces.add(Edm.NAMESPACE_EDM_2007_05);
+    edmNamespaces.add(Edm.NAMESPACE_EDM_2008_01);
+    edmNamespaces.add(Edm.NAMESPACE_EDM_2008_09);
+
+  }
+}


[04/24] olingo-odata2 git commit: [OLINGO-1253]Client Module for Olingo v2

Posted by ar...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/resources/JsonRoom_InlineEmployeesToTeam.json
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/resources/JsonRoom_InlineEmployeesToTeam.json b/odata2-lib/odata-client-core/src/test/resources/JsonRoom_InlineEmployeesToTeam.json
new file mode 100644
index 0000000..979e39a
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/resources/JsonRoom_InlineEmployeesToTeam.json
@@ -0,0 +1,79 @@
+{
+  "d": {
+    "__metadata": {
+      "id": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Rooms('1')",
+      "uri": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Rooms('1')",
+      "type": "RefScenario.Room",
+      "etag": "W/\"1\""
+    },
+    "Id": "1",
+    "Name": "Room 1",
+    "Seats": 1,
+    "Version": 1,
+    "nr_Employees": {
+      "results": [
+        {
+          "__metadata": {
+            "id": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Employees('1')",
+            "uri": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Employees('1')",
+            "type": "RefScenario.Employee",
+            "content_type": "image/jpeg",
+            "media_src": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Employees('1')/$value",
+            "edit_media": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Employees('1')/$value"
+          },
+          "EmployeeId": "1",
+          "EmployeeName": "Walter Winter",
+          "ManagerId": "1",
+          "RoomId": "1",
+          "TeamId": "1",
+          "Location": {
+            "__metadata": {
+              "type": "RefScenario.c_Location"
+            },
+            "City": {
+              "__metadata": {
+                "type": "RefScenario.c_City"
+              },
+              "PostalCode": "69124",
+              "CityName": "Heidelberg"
+            },
+            "Country": "Germany"
+          },
+          "Age": 52,
+          "EntryDate": "/Date(915148800000)/",
+          "ImageUrl": "Employees('1')/$value",
+          "ne_Manager": {
+            "__deferred": {
+              "uri": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Employees('1')/ne_Manager"
+            }
+          },
+          "ne_Team": {
+            "__metadata": {
+              "id": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Teams('1')",
+              "uri": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Teams('1')",
+              "type": "RefScenario.Team"
+            },
+            "Id": "1",
+            "Name": "Team 1",
+            "isScrumTeam": false,
+            "nt_Employees": {
+              "__deferred": {
+                "uri": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Teams('1')/nt_Employees"
+              }
+            }
+          },
+          "ne_Room": {
+            "__deferred": {
+              "uri": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Employees('1')/ne_Room"
+            }
+          }
+        }
+      ]
+    },
+    "nr_Building": {
+      "__deferred": {
+        "uri": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Rooms('1')/nr_Building"
+      }
+    }
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/resources/JsonRoomsToEmployeesWithInlineTeams.json
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/resources/JsonRoomsToEmployeesWithInlineTeams.json b/odata2-lib/odata-client-core/src/test/resources/JsonRoomsToEmployeesWithInlineTeams.json
new file mode 100644
index 0000000..671dbb6
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/resources/JsonRoomsToEmployeesWithInlineTeams.json
@@ -0,0 +1,118 @@
+{
+  "d": {
+    "results": [
+      {
+        "__metadata": {
+          "id": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Employees('2')",
+          "uri": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Employees('2')",
+          "type": "RefScenario.Employee",
+          "content_type": "image/jpeg",
+          "media_src": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Employees('2')/$value",
+          "edit_media": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Employees('2')/$value"
+        },
+        "EmployeeId": "2",
+        "EmployeeName": "Frederic Fall",
+        "ManagerId": "1",
+        "RoomId": "2",
+        "TeamId": "1",
+        "Location": {
+          "__metadata": {
+            "type": "RefScenario.c_Location"
+          },
+          "City": {
+            "__metadata": {
+              "type": "RefScenario.c_City"
+            },
+            "PostalCode": "69190",
+            "CityName": "Walldorf"
+          },
+          "Country": "Germany"
+        },
+        "Age": 32,
+        "EntryDate": "/Date(1057017600000)/",
+        "ImageUrl": "Employees('2')/$value",
+        "ne_Manager": {
+          "__deferred": {
+            "uri": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Employees('2')/ne_Manager"
+          }
+        },
+        "ne_Team": {
+          "__metadata": {
+            "id": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Teams('1')",
+            "uri": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Teams('1')",
+            "type": "RefScenario.Team"
+          },
+          "Id": "1",
+          "Name": "Team 1",
+          "isScrumTeam": false,
+          "nt_Employees": {
+            "__deferred": {
+              "uri": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Teams('1')/nt_Employees"
+            }
+          }
+        },
+        "ne_Room": {
+          "__deferred": {
+            "uri": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Employees('2')/ne_Room"
+          }
+        }
+      },
+      {
+        "__metadata": {
+          "id": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Employees('6')",
+          "uri": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Employees('6')",
+          "type": "RefScenario.Employee",
+          "content_type": "image/jpeg",
+          "media_src": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Employees('6')/$value",
+          "edit_media": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Employees('6')/$value"
+        },
+        "EmployeeId": "6",
+        "EmployeeName": "Susan Bay",
+        "ManagerId": "1",
+        "RoomId": "2",
+        "TeamId": "3",
+        "Location": {
+          "__metadata": {
+            "type": "RefScenario.c_Location"
+          },
+          "City": {
+            "__metadata": {
+              "type": "RefScenario.c_City"
+            },
+            "PostalCode": "69190",
+            "CityName": "Walldorf"
+          },
+          "Country": "Germany"
+        },
+        "Age": 29,
+        "EntryDate": "/Date(1291161600000)/",
+        "ImageUrl": "Employees('6')/$value",
+        "ne_Manager": {
+          "__deferred": {
+            "uri": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Employees('6')/ne_Manager"
+          }
+        },
+        "ne_Team": {
+          "__metadata": {
+            "id": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Teams('3')",
+            "uri": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Teams('3')",
+            "type": "RefScenario.Team"
+          },
+          "Id": "3",
+          "Name": "Team 3",
+          "isScrumTeam": false,
+          "nt_Employees": {
+            "__deferred": {
+              "uri": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Teams('3')/nt_Employees"
+            }
+          }
+        },
+        "ne_Room": {
+          "__deferred": {
+            "uri": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Employees('6')/ne_Room"
+          }
+        }
+      }
+    ]
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/resources/JsonRooms_InlineEmployeesTeams.json
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/resources/JsonRooms_InlineEmployeesTeams.json b/odata2-lib/odata-client-core/src/test/resources/JsonRooms_InlineEmployeesTeams.json
new file mode 100644
index 0000000..b466ad2
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/resources/JsonRooms_InlineEmployeesTeams.json
@@ -0,0 +1,236 @@
+{
+  "d": {
+    "results": [
+      {
+        "__metadata": {
+          "id": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Rooms('1')",
+          "uri": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Rooms('1')",
+          "type": "RefScenario.Room",
+          "etag": "W/\"1\""
+        },
+        "Id": "1",
+        "Name": "Room 1",
+        "Seats": 1,
+        "Version": 1,
+        "nr_Employees": {
+          "results": [
+            {
+              "__metadata": {
+                "id": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Employees('1')",
+                "uri": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Employees('1')",
+                "type": "RefScenario.Employee",
+                "content_type": "image/jpeg",
+                "media_src": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Employees('1')/$value",
+                "edit_media": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Employees('1')/$value"
+              },
+              "EmployeeId": "1",
+              "EmployeeName": "Walter Winter",
+              "ManagerId": "1",
+              "RoomId": "1",
+              "TeamId": "1",
+              "Location": {
+                "__metadata": {
+                  "type": "RefScenario.c_Location"
+                },
+                "City": {
+                  "__metadata": {
+                    "type": "RefScenario.c_City"
+                  },
+                  "PostalCode": "69124",
+                  "CityName": "Heidelberg"
+                },
+                "Country": "Germany"
+              },
+              "Age": 52,
+              "EntryDate": "/Date(915148800000)/",
+              "ImageUrl": "Employees('1')/$value",
+              "ne_Manager": {
+                "__deferred": {
+                  "uri": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Employees('1')/ne_Manager"
+                }
+              },
+              "ne_Team": {
+                "__metadata": {
+                  "id": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Teams('1')",
+                  "uri": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Teams('1')",
+                  "type": "RefScenario.Team"
+                },
+                "Id": "1",
+                "Name": "Team 1",
+                "isScrumTeam": false,
+                "nt_Employees": {
+                  "__deferred": {
+                    "uri": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Teams('1')/nt_Employees"
+                  }
+                }
+              },
+              "ne_Room": {
+                "__deferred": {
+                  "uri": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Employees('1')/ne_Room"
+                }
+              }
+            }
+          ]
+        },
+        "nr_Building": {
+          "__deferred": {
+            "uri": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Rooms('1')/nr_Building"
+          }
+        }
+      },
+      {
+        "__metadata": {
+          "id": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Rooms('10')",
+          "uri": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Rooms('10')",
+          "type": "RefScenario.Room",
+          "etag": "W/\"1\""
+        },
+        "Id": "10",
+        "Name": "Room 10",
+        "Seats": 6,
+        "Version": 1,
+        "nr_Employees": {
+          "results": []
+        },
+        "nr_Building": {
+          "__deferred": {
+            "uri": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Rooms('10')/nr_Building"
+          }
+        }
+      },
+      {
+        "__metadata": {
+          "id": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Rooms('2')",
+          "uri": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Rooms('2')",
+          "type": "RefScenario.Room",
+          "etag": "W/\"2\""
+        },
+        "Id": "2",
+        "Name": "Room 2",
+        "Seats": 5,
+        "Version": 2,
+        "nr_Employees": {
+          "results": [
+            {
+              "__metadata": {
+                "id": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Employees('2')",
+                "uri": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Employees('2')",
+                "type": "RefScenario.Employee",
+                "content_type": "image/jpeg",
+                "media_src": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Employees('2')/$value",
+                "edit_media": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Employees('2')/$value"
+              },
+              "EmployeeId": "2",
+              "EmployeeName": "Frederic Fall",
+              "ManagerId": "1",
+              "RoomId": "2",
+              "TeamId": "1",
+              "Location": {
+                "__metadata": {
+                  "type": "RefScenario.c_Location"
+                },
+                "City": {
+                  "__metadata": {
+                    "type": "RefScenario.c_City"
+                  },
+                  "PostalCode": "69190",
+                  "CityName": "Walldorf"
+                },
+                "Country": "Germany"
+              },
+              "Age": 32,
+              "EntryDate": "/Date(1057017600000)/",
+              "ImageUrl": "Employees('2')/$value",
+              "ne_Manager": {
+                "__deferred": {
+                  "uri": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Employees('2')/ne_Manager"
+                }
+              },
+              "ne_Team": {
+                "__metadata": {
+                  "id": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Teams('1')",
+                  "uri": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Teams('1')",
+                  "type": "RefScenario.Team"
+                },
+                "Id": "1",
+                "Name": "Team 1",
+                "isScrumTeam": false,
+                "nt_Employees": {
+                  "__deferred": {
+                    "uri": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Teams('1')/nt_Employees"
+                  }
+                }
+              },
+              "ne_Room": {
+                "__deferred": {
+                  "uri": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Employees('2')/ne_Room"
+                }
+              }
+            },
+            {
+              "__metadata": {
+                "id": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Employees('3')",
+                "uri": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Employees('3')",
+                "type": "RefScenario.Employee",
+                "content_type": "image/jpeg",
+                "media_src": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Employees('3')/$value",
+                "edit_media": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Employees('3')/$value"
+              },
+              "EmployeeId": "3",
+              "EmployeeName": "Jonathan Smith",
+              "ManagerId": "1",
+              "RoomId": "2",
+              "TeamId": "1",
+              "Location": {
+                "__metadata": {
+                  "type": "RefScenario.c_Location"
+                },
+                "City": {
+                  "__metadata": {
+                    "type": "RefScenario.c_City"
+                  },
+                  "PostalCode": "69190",
+                  "CityName": "Walldorf"
+                },
+                "Country": "Germany"
+              },
+              "Age": 56,
+              "EntryDate": null,
+              "ImageUrl": "Employees('3')/$value",
+              "ne_Manager": {
+                "__deferred": {
+                  "uri": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Employees('3')/ne_Manager"
+                }
+              },
+              "ne_Team": {
+                "__metadata": {
+                  "id": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Teams('1')",
+                  "uri": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Teams('1')",
+                  "type": "RefScenario.Team"
+                },
+                "Id": "1",
+                "Name": "Team 1",
+                "isScrumTeam": false,
+                "nt_Employees": {
+                  "__deferred": {
+                    "uri": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Teams('1')/nt_Employees"
+                  }
+                }
+              },
+              "ne_Room": {
+                "__deferred": {
+                  "uri": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Employees('3')/ne_Room"
+                }
+              }
+            }
+          ]
+        },
+        "nr_Building": {
+          "__deferred": {
+            "uri": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Rooms('2')/nr_Building"
+          }
+        }
+      }
+    ]
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/resources/JsonRooms_InlineEmployees_InlineBuilding.json
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/resources/JsonRooms_InlineEmployees_InlineBuilding.json b/odata2-lib/odata-client-core/src/test/resources/JsonRooms_InlineEmployees_InlineBuilding.json
new file mode 100644
index 0000000..3d1747f
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/resources/JsonRooms_InlineEmployees_InlineBuilding.json
@@ -0,0 +1,236 @@
+{
+  "d": {
+    "results": [
+      {
+        "__metadata": {
+          "id": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Rooms('1')",
+          "uri": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Rooms('1')",
+          "type": "RefScenario.Room",
+          "etag": "W/\"1\""
+        },
+        "Id": "1",
+        "Name": "Room 1",
+        "Seats": 1,
+        "Version": 1,
+        "nr_Employees": {
+          "results": [
+            {
+              "__metadata": {
+                "id": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Employees('1')",
+                "uri": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Employees('1')",
+                "type": "RefScenario.Employee",
+                "content_type": "image/jpeg",
+                "media_src": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Employees('1')/$value",
+                "edit_media": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Employees('1')/$value"
+              },
+              "EmployeeId": "1",
+              "EmployeeName": "Walter Winter",
+              "ManagerId": "1",
+              "RoomId": "1",
+              "TeamId": "1",
+              "Location": {
+                "__metadata": {
+                  "type": "RefScenario.c_Location"
+                },
+                "City": {
+                  "__metadata": {
+                    "type": "RefScenario.c_City"
+                  },
+                  "PostalCode": "69124",
+                  "CityName": "Heidelberg"
+                },
+                "Country": "Germany"
+              },
+              "Age": 52,
+              "EntryDate": "/Date(915148800000)/",
+              "ImageUrl": "Employees('1')/$value",
+              "ne_Manager": {
+                "__deferred": {
+                  "uri": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Employees('1')/ne_Manager"
+                }
+              },
+              "ne_Team": {
+                "__deferred": {
+                  "uri": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Employees('1')/ne_Team"
+                }
+              },
+              "ne_Room": {
+                "__deferred": {
+                  "uri": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Employees('1')/ne_Room"
+                }
+              }
+            }
+          ]
+        },
+        "nr_Building": {
+          "__metadata": {
+            "id": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Buildings('1')",
+            "uri": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Buildings('1')",
+            "type": "RefScenario.Building"
+          },
+          "Id": "1",
+          "Name": "Building 1",
+          "Image": null,
+          "nb_Rooms": {
+            "__deferred": {
+              "uri": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Buildings('1')/nb_Rooms"
+            }
+          }
+        }
+      },
+      {
+        "__metadata": {
+          "id": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Rooms('10')",
+          "uri": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Rooms('10')",
+          "type": "RefScenario.Room",
+          "etag": "W/\"1\""
+        },
+        "Id": "10",
+        "Name": "Room 10",
+        "Seats": 6,
+        "Version": 1,
+        "nr_Employees": {
+          "results": []
+        },
+        "nr_Building": {
+          "__metadata": {
+            "id": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Buildings('3')",
+            "uri": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Buildings('3')",
+            "type": "RefScenario.Building"
+          },
+          "Id": "3",
+          "Name": "Building 3",
+          "Image": null,
+          "nb_Rooms": {
+            "__deferred": {
+              "uri": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Buildings('3')/nb_Rooms"
+            }
+          }
+        }
+      },
+	  {
+        "__metadata": {
+          "id": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Rooms('2')",
+          "uri": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Rooms('2')",
+          "type": "RefScenario.Room",
+          "etag": "W/\"2\""
+        },
+        "Id": "2",
+        "Name": "Room 2",
+        "Seats": 5,
+        "Version": 2,
+        "nr_Employees": {
+          "results": [
+            {
+              "__metadata": {
+                "id": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Employees('2')",
+                "uri": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Employees('2')",
+                "type": "RefScenario.Employee",
+                "content_type": "image/jpeg",
+                "media_src": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Employees('2')/$value",
+                "edit_media": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Employees('2')/$value"
+              },
+              "EmployeeId": "2",
+              "EmployeeName": "Frederic Fall",
+              "ManagerId": "1",
+              "RoomId": "2",
+              "TeamId": "1",
+              "Location": {
+                "__metadata": {
+                  "type": "RefScenario.c_Location"
+                },
+                "City": {
+                  "__metadata": {
+                    "type": "RefScenario.c_City"
+                  },
+                  "PostalCode": "69190",
+                  "CityName": "Walldorf"
+                },
+                "Country": "Germany"
+              },
+              "Age": 32,
+              "EntryDate": "/Date(1057017600000)/",
+              "ImageUrl": "Employees('2')/$value",
+              "ne_Manager": {
+                "__deferred": {
+                  "uri": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Employees('2')/ne_Manager"
+                }
+              },
+              "ne_Team": {
+                "__deferred": {
+                  "uri": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Employees('2')/ne_Team"
+                }
+              },
+              "ne_Room": {
+                "__deferred": {
+                  "uri": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Employees('2')/ne_Room"
+                }
+              }
+            },
+            {
+              "__metadata": {
+                "id": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Employees('3')",
+                "uri": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Employees('3')",
+                "type": "RefScenario.Employee",
+                "content_type": "image/jpeg",
+                "media_src": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Employees('3')/$value",
+                "edit_media": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Employees('3')/$value"
+              },
+              "EmployeeId": "3",
+              "EmployeeName": "Jonathan Smith",
+              "ManagerId": "1",
+              "RoomId": "2",
+              "TeamId": "1",
+              "Location": {
+                "__metadata": {
+                  "type": "RefScenario.c_Location"
+                },
+                "City": {
+                  "__metadata": {
+                    "type": "RefScenario.c_City"
+                  },
+                  "PostalCode": "69190",
+                  "CityName": "Walldorf"
+                },
+                "Country": "Germany"
+              },
+              "Age": 56,
+              "EntryDate": null,
+              "ImageUrl": "Employees('3')/$value",
+              "ne_Manager": {
+                "__deferred": {
+                  "uri": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Employees('3')/ne_Manager"
+                }
+              },
+              "ne_Team": {
+                "__deferred": {
+                  "uri": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Employees('3')/ne_Team"
+                }
+              },
+              "ne_Room": {
+                "__deferred": {
+                  "uri": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Employees('3')/ne_Room"
+                }
+              }
+            }
+          ]
+        },
+        "nr_Building": {
+          "__metadata": {
+            "id": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Buildings('2')",
+            "uri": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Buildings('2')",
+            "type": "RefScenario.Building"
+          },
+          "Id": "2",
+          "Name": "Building 2",
+          "Image": null,
+          "nb_Rooms": {
+            "__deferred": {
+              "uri": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Buildings('2')/nb_Rooms"
+            }
+          }
+        }
+      }
+    ]
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/resources/JsonTeam.json
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/resources/JsonTeam.json b/odata2-lib/odata-client-core/src/test/resources/JsonTeam.json
new file mode 100644
index 0000000..50e1694
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/resources/JsonTeam.json
@@ -0,0 +1,17 @@
+{
+	"d" : {
+		"__metadata" : {
+			"id" : "http://localhost:8080/ReferenceScenario.svc/Teams('1')",
+			"uri" : "http://localhost:8080/ReferenceScenario.svc/Teams('1')",
+			"type" : "RefScenario.Team"
+		},
+		"Id" : "1",
+		"Name" : "Team 1",
+		"isScrumTeam" : false,
+		"nt_Employees" : {
+			"__deferred" : {
+				"uri" : "http://localhost:8080/ReferenceScenario.svc/Teams('1')/nt_Employees"
+			}
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/resources/JsonTeams.json
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/resources/JsonTeams.json b/odata2-lib/odata-client-core/src/test/resources/JsonTeams.json
new file mode 100644
index 0000000..4743c84
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/resources/JsonTeams.json
@@ -0,0 +1,34 @@
+{
+	"d" : {
+		"results" : [{
+				"__metadata" : {
+					"id" : "http://localhost:8080/ReferenceScenario.svc/Teams('1')",
+					"uri" : "http://localhost:8080/ReferenceScenario.svc/Teams('1')",
+					"type" : "RefScenario.Team"
+				},
+				"Id" : "1",
+				"Name" : "Team 1",
+				"isScrumTeam" : false,
+				"nt_Employees" : {
+					"__deferred" : {
+						"uri" : "http://localhost:8080/ReferenceScenario.svc/Teams('1')/nt_Employees"
+					}
+				}
+			}, {
+				"__metadata" : {
+					"id" : "http://localhost:8080/ReferenceScenario.svc/Teams('2')",
+					"uri" : "http://localhost:8080/ReferenceScenario.svc/Teams('2')",
+					"type" : "RefScenario.Team"
+				},
+				"Id" : "2",
+				"Name" : "Team 2",
+				"isScrumTeam" : true,
+				"nt_Employees" : {
+					"__deferred" : {
+						"uri" : "http://localhost:8080/ReferenceScenario.svc/Teams('2')/nt_Employees"
+					}
+				}
+			}
+		]
+	}
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/resources/JsonTeamsWithCount.json
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/resources/JsonTeamsWithCount.json b/odata2-lib/odata-client-core/src/test/resources/JsonTeamsWithCount.json
new file mode 100644
index 0000000..b76fff8
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/resources/JsonTeamsWithCount.json
@@ -0,0 +1,35 @@
+{
+	"d" : {
+		"__count" : "3",
+		"results" : [{
+				"__metadata" : {
+					"id" : "http://localhost:8080/ReferenceScenario.svc/Teams('2')",
+					"uri" : "http://localhost:8080/ReferenceScenario.svc/Teams('2')",
+					"type" : "RefScenario.Team"
+				},
+				"Id" : "2",
+				"Name" : "Team 2",
+				"isScrumTeam" : true,
+				"nt_Employees" : {
+					"__deferred" : {
+						"uri" : "http://localhost:8080/ReferenceScenario.svc/Teams('2')/nt_Employees"
+					}
+				}
+			}, {
+				"__metadata" : {
+					"id" : "http://localhost:8080/ReferenceScenario.svc/Teams('3')",
+					"uri" : "http://localhost:8080/ReferenceScenario.svc/Teams('3')",
+					"type" : "RefScenario.Team"
+				},
+				"Id" : "3",
+				"Name" : "Team 3",
+				"isScrumTeam" : false,
+				"nt_Employees" : {
+					"__deferred" : {
+						"uri" : "http://localhost:8080/ReferenceScenario.svc/Teams('3')/nt_Employees"
+					}
+				}
+			}
+		]
+	}
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/resources/JsonTeamsWithCountWithoutD.json
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/resources/JsonTeamsWithCountWithoutD.json b/odata2-lib/odata-client-core/src/test/resources/JsonTeamsWithCountWithoutD.json
new file mode 100644
index 0000000..a0231e6
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/resources/JsonTeamsWithCountWithoutD.json
@@ -0,0 +1,34 @@
+{
+		"__count" : "3",
+		"results" : [{
+				"__metadata" : {
+					"id" : "http://localhost:8080/ReferenceScenario.svc/Teams('2')",
+					"uri" : "http://localhost:8080/ReferenceScenario.svc/Teams('2')",
+					"type" : "RefScenario.Team"
+				},
+				"Id" : "2",
+				"Name" : "Team 2",
+				"isScrumTeam" : true,
+				"nt_Employees" : {
+					"__deferred" : {
+						"uri" : "http://localhost:8080/ReferenceScenario.svc/Teams('2')/nt_Employees"
+					}
+				}
+			}, {
+				"__metadata" : {
+					"id" : "http://localhost:8080/ReferenceScenario.svc/Teams('3')",
+					"uri" : "http://localhost:8080/ReferenceScenario.svc/Teams('3')",
+					"type" : "RefScenario.Team"
+				},
+				"Id" : "3",
+				"Name" : "Team 3",
+				"isScrumTeam" : false,
+				"nt_Employees" : {
+					"__deferred" : {
+						"uri" : "http://localhost:8080/ReferenceScenario.svc/Teams('3')/nt_Employees"
+					}
+				}
+			}
+		]
+	}
+

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/resources/JsonTeamsWithInlineEmployees.json
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/resources/JsonTeamsWithInlineEmployees.json b/odata2-lib/odata-client-core/src/test/resources/JsonTeamsWithInlineEmployees.json
new file mode 100644
index 0000000..568bbc9
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/resources/JsonTeamsWithInlineEmployees.json
@@ -0,0 +1,151 @@
+{
+	"d" : {
+		"__metadata" : {
+			"id" : "http://localhost:8080/ReferenceScenario.svc/Teams('1')",
+			"uri" : "http://localhost:8080/ReferenceScenario.svc/Teams('1')",
+			"type" : "RefScenario.Team"
+		},
+		"Id" : "1",
+		"Name" : "Team 1",
+		"isScrumTeam" : false,
+		"nt_Employees" : {
+			"results" : [{
+					"__metadata" : {
+						"id" : "http://localhost:8080/ReferenceScenario.svc/Employees('1')",
+						"uri" : "http://localhost:8080/ReferenceScenario.svc/Employees('1')",
+						"type" : "RefScenario.Employee",
+						"content_type" : "image/jpeg",
+						"media_src" : "Employees('1')/$value",
+						"edit_media" : "http://localhost:8080/ReferenceScenario.svc/Employees('1')/$value"
+					},
+					"EmployeeId" : "1",
+					"EmployeeName" : "Walter Winter",
+					"ManagerId" : "1",
+					"RoomId" : "1",
+					"TeamId" : "1",
+					"Location" : {
+						"__metadata" : {
+							"type" : "RefScenario.c_Location"
+						},
+						"City" : {
+							"__metadata" : {
+								"type" : "RefScenario.c_City"
+							},
+							"PostalCode" : "69124",
+							"CityName" : "Heidelberg"
+						},
+						"Country" : "Germany"
+					},
+					"Age" : 52,
+					"EntryDate" : "\/Date(915148800000)\/",
+					"ImageUrl" : "Employees('1')/$value",
+					"ne_Manager" : {
+						"__deferred" : {
+							"uri" : "http://localhost:8080/ReferenceScenario.svc/Employees('1')/ne_Manager"
+						}
+					},
+					"ne_Team" : {
+						"__deferred" : {
+							"uri" : "http://localhost:8080/ReferenceScenario.svc/Employees('1')/ne_Team"
+						}
+					},
+					"ne_Room" : {
+						"__deferred" : {
+							"uri" : "http://localhost:8080/ReferenceScenario.svc/Employees('1')/ne_Room"
+						}
+					}
+				}, {
+					"__metadata" : {
+						"id" : "http://localhost:8080/ReferenceScenario.svc/Employees('2')",
+						"uri" : "http://localhost:8080/ReferenceScenario.svc/Employees('2')",
+						"type" : "RefScenario.Employee",
+						"content_type" : "image/jpeg",
+						"media_src" : "Employees('2')/$value",
+						"edit_media" : "http://localhost:8080/ReferenceScenario.svc/Employees('2')/$value"
+					},
+					"EmployeeId" : "2",
+					"EmployeeName" : "Frederic Fall",
+					"ManagerId" : "1",
+					"RoomId" : "2",
+					"TeamId" : "1",
+					"Location" : {
+						"__metadata" : {
+							"type" : "RefScenario.c_Location"
+						},
+						"City" : {
+							"__metadata" : {
+								"type" : "RefScenario.c_City"
+							},
+							"PostalCode" : "69190",
+							"CityName" : "Walldorf"
+						},
+						"Country" : "Germany"
+					},
+					"Age" : 32,
+					"EntryDate" : "\/Date(1057017600000)\/",
+					"ImageUrl" : "Employees('2')/$value",
+					"ne_Manager" : {
+						"__deferred" : {
+							"uri" : "http://localhost:8080/ReferenceScenario.svc/Employees('2')/ne_Manager"
+						}
+					},
+					"ne_Team" : {
+						"__deferred" : {
+							"uri" : "http://localhost:8080/ReferenceScenario.svc/Employees('2')/ne_Team"
+						}
+					},
+					"ne_Room" : {
+						"__deferred" : {
+							"uri" : "http://localhost:8080/ReferenceScenario.svc/Employees('2')/ne_Room"
+						}
+					}
+				}, {
+					"__metadata" : {
+						"id" : "http://localhost:8080/ReferenceScenario.svc/Employees('3')",
+						"uri" : "http://localhost:8080/ReferenceScenario.svc/Employees('3')",
+						"type" : "RefScenario.Employee",
+						"content_type" : "image/jpeg",
+						"media_src" : "Employees('3')/$value",
+						"edit_media" : "http://localhost:8080/ReferenceScenario.svc/Employees('3')/$value"
+					},
+					"EmployeeId" : "3",
+					"EmployeeName" : "Jonathan Smith",
+					"ManagerId" : "1",
+					"RoomId" : "2",
+					"TeamId" : "1",
+					"Location" : {
+						"__metadata" : {
+							"type" : "RefScenario.c_Location"
+						},
+						"City" : {
+							"__metadata" : {
+								"type" : "RefScenario.c_City"
+							},
+							"PostalCode" : "69190",
+							"CityName" : "Walldorf"
+						},
+						"Country" : "Germany"
+					},
+					"Age" : 56,
+					"EntryDate" : null,
+					"ImageUrl" : "Employees('3')/$value",
+					"ne_Manager" : {
+						"__deferred" : {
+							"uri" : "http://localhost:8080/ReferenceScenario.svc/Employees('3')/ne_Manager"
+						}
+					},
+					"ne_Team" : {
+						"__deferred" : {
+							"uri" : "http://localhost:8080/ReferenceScenario.svc/Employees('3')/ne_Team"
+						}
+					},
+					"ne_Room" : {
+						"__deferred" : {
+							"uri" : "http://localhost:8080/ReferenceScenario.svc/Employees('3')/ne_Room"
+						}
+					}
+				}
+			]
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/resources/JsonTeamsWithoutD.json
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/resources/JsonTeamsWithoutD.json b/odata2-lib/odata-client-core/src/test/resources/JsonTeamsWithoutD.json
new file mode 100644
index 0000000..5848584
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/resources/JsonTeamsWithoutD.json
@@ -0,0 +1,33 @@
+{
+		"results" : [{
+				"__metadata" : {
+					"id" : "http://localhost:8080/ReferenceScenario.svc/Teams('1')",
+					"uri" : "http://localhost:8080/ReferenceScenario.svc/Teams('1')",
+					"type" : "RefScenario.Team"
+				},
+				"Id" : "1",
+				"Name" : "Team 1",
+				"isScrumTeam" : false,
+				"nt_Employees" : {
+					"__deferred" : {
+						"uri" : "http://localhost:8080/ReferenceScenario.svc/Teams('1')/nt_Employees"
+					}
+				}
+			}, {
+				"__metadata" : {
+					"id" : "http://localhost:8080/ReferenceScenario.svc/Teams('2')",
+					"uri" : "http://localhost:8080/ReferenceScenario.svc/Teams('2')",
+					"type" : "RefScenario.Team"
+				},
+				"Id" : "2",
+				"Name" : "Team 2",
+				"isScrumTeam" : true,
+				"nt_Employees" : {
+					"__deferred" : {
+						"uri" : "http://localhost:8080/ReferenceScenario.svc/Teams('2')/nt_Employees"
+					}
+				}
+			}
+		]
+}
+

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/resources/JsonWithDeletedEntries.json
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/resources/JsonWithDeletedEntries.json b/odata2-lib/odata-client-core/src/test/resources/JsonWithDeletedEntries.json
new file mode 100644
index 0000000..00eabe3
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/resources/JsonWithDeletedEntries.json
@@ -0,0 +1,30 @@
+{
+"d": {
+"results": [
+  {
+    "__metadata": 
+        { 
+            "id": "http://ldcigmd.wdf.sap.corp:50055/sap/bc/odata/Rooms('1')", 
+            "uri": "http://ldcigmd.wdf.sap.corp:50055/sap/bc/odata/Rooms('1')", 
+            "type": "RefScenario.Room", 
+           "etag":"W/\"2\""
+        },
+    "Id": "1",
+    "Name": "Room 1",
+    "Seats": 1,
+    "Version": 1
+  },
+     {
+        "@odata.context":"$metadata#Rooms/$deletedEntity",
+        "id":"http://host:80/service/Rooms('3')",
+        "when":"\/Date(1300561560000)\/"
+     },
+     {
+        "@odata.context":"$metadata#Rooms/$deletedEntity",
+        "id":"http://host:80/service/Rooms('4')",
+        "when":"\/Date(3509636760000)\/"
+     }
+],
+"__delta":"http://localhost:8080/ReferenceScenario.svc/Rooms?!deltatoken=4711"
+}
+}
\ No newline at end of file


[10/24] olingo-odata2 git commit: [OLINGO-1253]Client Module for Olingo v2

Posted by ar...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/serializer/AtomEntrySerializerTest.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/serializer/AtomEntrySerializerTest.java b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/serializer/AtomEntrySerializerTest.java
new file mode 100644
index 0000000..74cab47
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/serializer/AtomEntrySerializerTest.java
@@ -0,0 +1,1814 @@
+/*******************************************************************************
+ * 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.client.core.ep.serializer;
+
+import static org.custommonkey.xmlunit.XMLAssert.assertXpathEvaluatesTo;
+import static org.custommonkey.xmlunit.XMLAssert.assertXpathExists;
+import static org.custommonkey.xmlunit.XMLAssert.assertXpathNotExists;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.TimeZone;
+
+import javax.xml.stream.FactoryConfigurationError;
+import javax.xml.stream.XMLStreamException;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmConcurrencyMode;
+import org.apache.olingo.odata2.api.edm.EdmCustomizableFeedMappings;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmEntityType;
+import org.apache.olingo.odata2.api.edm.EdmFacets;
+import org.apache.olingo.odata2.api.edm.EdmMapping;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.edm.EdmTargetPath;
+import org.apache.olingo.odata2.api.edm.EdmTyped;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.api.exception.ODataMessageException;
+import org.apache.olingo.odata2.api.processor.ODataResponse;
+import org.apache.olingo.odata2.client.api.edm.ClientEdm;
+import org.apache.olingo.odata2.client.api.edm.EdmDataServices;
+import org.apache.olingo.odata2.client.api.ep.Entity;
+import org.apache.olingo.odata2.client.api.ep.EntityCollection;
+import org.apache.olingo.odata2.client.api.ep.EntitySerializerProperties;
+import org.apache.olingo.odata2.client.core.ep.AbstractProviderTest;
+import org.apache.olingo.odata2.client.core.ep.AtomSerializerDeserializer;
+import org.apache.olingo.odata2.client.core.ep.deserializer.XmlMetadataDeserializer;
+import org.apache.olingo.odata2.core.commons.ContentType;
+import org.apache.olingo.odata2.core.ep.EntityProviderProducerException;
+import org.apache.olingo.odata2.testutil.helper.StringHelper;
+import org.apache.olingo.odata2.testutil.helper.XMLUnitHelper;
+import org.apache.olingo.odata2.testutil.mock.MockFacade;
+import org.custommonkey.xmlunit.SimpleNamespaceContext;
+import org.custommonkey.xmlunit.XMLUnit;
+import org.custommonkey.xmlunit.exceptions.XpathException;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.xml.sax.SAXException;
+
+import junit.framework.Assert;
+
+public class AtomEntrySerializerTest extends AbstractProviderTest {
+
+  @Rule
+  public ExpectedException expectedEx = ExpectedException.none();
+
+  private String buildingXPathString = "/a:entry/a:link[@href=\"Rooms('1')/nr_Building\" and @title='nr_Building']";  
+
+  private String productXPathString = "/a:entry/a:link[@href=\"A_Product('CRPROD2')/to_Description\" "
+      + "and @title='to_Description']";
+  
+  public AtomEntrySerializerTest(final StreamWriterImplType type) {
+    super(type);
+  }
+
+  @Test
+  public void contentOnly() throws Exception {
+    final EntitySerializerProperties properties =
+        EntitySerializerProperties.serviceRoot(BASE_URI).includeMetadata(false).build();
+
+    AtomSerializerDeserializer ser = createAtomEntityProvider();
+    employeeData.setWriteProperties(properties);
+    ODataResponse response =
+        ser.writeEntry(MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees"), employeeData);
+    String xmlString = verifyResponse(response);
+    assertXpathExists("/a:entry", xmlString);
+    assertXpathEvaluatesTo(BASE_URI.toASCIIString(), "/a:entry/@xml:base", xmlString);
+
+    assertXpathNotExists("/a:entry[@m:etag]", xmlString);
+    assertXpathNotExists("/a:entry/a:id", xmlString);
+    assertXpathNotExists("/a:entry/a:title", xmlString);
+    assertXpathNotExists("/a:entry/a:updated", xmlString);
+    assertXpathNotExists("/a:entry/a:category", xmlString);
+    assertXpathNotExists("/a:entry/a:link[@title=\"ne_Team\"and @href=\"Employees('1')/ne_Team\"]", xmlString);
+    assertXpathNotExists("/a:entry/a:link[@title=\"ne_Room\"and @href=\"Employees('1')/ne_Room\"]", xmlString);
+    assertXpathNotExists("/a:entry/a:link[@title=\"ne_Manager\" and @href=\"Employees('1')/ne_Manager\"]", xmlString);
+    assertXpathNotExists("/a:entry/a:content", xmlString);
+
+    assertXpathExists("/a:entry/m:properties", xmlString);
+  }
+
+  @Test
+  public void emptyRoomWithProperty() throws Exception {
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+
+    final EntitySerializerProperties properties =
+        EntitySerializerProperties.serviceRoot(BASE_URI).includeMetadata(false)
+            .build();
+
+    Entity localRoomData = new Entity();
+    localRoomData.setWriteProperties(properties);
+    AtomSerializerDeserializer ser = createAtomEntityProvider();
+    ODataResponse response = ser.writeEntry(entitySet, localRoomData);
+    String xmlString = verifyResponse(response);
+    assertXpathExists("/a:entry", xmlString);
+    assertXpathEvaluatesTo(BASE_URI.toASCIIString(), "/a:entry/@xml:base", xmlString);
+    assertXpathNotExists("/a:entry[@m:etag]", xmlString);
+
+    assertXpathNotExists("/a:entry/a:id", xmlString);
+    assertXpathNotExists("/a:entry/a:title", xmlString);
+    assertXpathNotExists("/a:entry/a:updated", xmlString);
+    assertXpathNotExists("/a:entry/a:category", xmlString);
+    assertXpathNotExists("/a:entry/a:link[@title=\"nr_Employees\"and @href=\"Rooms('1')/nr_Employees\"]", xmlString);
+    assertXpathNotExists("/a:entry/a:link[@title=\"nr_Building\"and @href=\"Rooms('1')/nr_Building\"]", xmlString);
+
+    assertXpathNotExists("/a:entry/a:content/m:properties/d:Name", xmlString);
+  }
+
+  @Test
+  public void emptyRoomWithoutProperty() throws Exception {
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+
+    expectedEx.expect(EntityProviderException.class);
+    expectedEx.expectMessage("Write properties are mandatory for XML.");
+    Entity localRoomData = new Entity();
+    AtomSerializerDeserializer ser = createAtomEntityProvider();
+    ser.writeEntry(entitySet, localRoomData);
+ }
+
+  @Test
+  public void nullRoom() throws Exception {
+    expectedEx.expect(EntityProviderException.class);
+    expectedEx.expectMessage("Entity or expanded entity cannot have null value.");
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+
+    AtomSerializerDeserializer ser = createAtomEntityProvider();
+    ser.writeEntry(entitySet, null);  
+  }
+
+  @Test
+  public void contentOnlyRoom() throws Exception {
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+
+    final EntitySerializerProperties properties =
+        EntitySerializerProperties.serviceRoot(BASE_URI).includeMetadata(false)
+            .build();
+
+    Entity localRoomData = new Entity();
+    localRoomData.addProperty("Name", "Neu Schwanstein");
+    localRoomData.setWriteProperties(properties);
+    AtomSerializerDeserializer ser = createAtomEntityProvider();
+    ODataResponse response = ser.writeEntry(entitySet, localRoomData);
+    String xmlString = verifyResponse(response);
+    assertXpathExists("/a:entry", xmlString);
+    assertXpathEvaluatesTo(BASE_URI.toASCIIString(), "/a:entry/@xml:base", xmlString);
+    assertXpathNotExists("/a:entry[@m:etag]", xmlString);
+
+    assertXpathNotExists("/a:entry/a:id", xmlString);
+    assertXpathNotExists("/a:entry/a:title", xmlString);
+    assertXpathNotExists("/a:entry/a:updated", xmlString);
+    assertXpathNotExists("/a:entry/a:category", xmlString);
+    assertXpathNotExists("/a:entry/a:link[@title=\"nr_Employees\"and @href=\"Rooms('1')/nr_Employees\"]", xmlString);
+    assertXpathNotExists("/a:entry/a:link[@title=\"nr_Building\"and @href=\"Rooms('1')/nr_Building\"]", xmlString);
+
+    assertXpathExists("/a:entry/a:content/m:properties/d:Name", xmlString);
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void contentOnlyRoomEmptyNullNavigationLinks() throws Exception {
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+
+    final EntitySerializerProperties properties =
+        EntitySerializerProperties.serviceRoot(BASE_URI).includeMetadata(true)
+            .build();
+
+    Entity localRoomData = new Entity();
+    localRoomData.addProperty("Name", "Neu Schwanstein");
+    localRoomData.setWriteProperties(properties);
+    localRoomData.addNavigation("nr_Employees", null);
+    localRoomData.addNavigation("nr_Building", new Entity());
+    AtomSerializerDeserializer ser = createAtomEntityProvider();
+    ODataResponse response = ser.writeEntry(entitySet, localRoomData);
+    String xmlString = verifyResponse(response);
+    assertXpathExists("/a:entry", xmlString);
+    assertXpathEvaluatesTo(BASE_URI.toASCIIString(), "/a:entry/@xml:base", xmlString);
+    assertXpathNotExists("/a:entry[@m:etag]", xmlString);
+
+    assertXpathNotExists("/a:entry/a:id", xmlString);
+    assertXpathNotExists("/a:entry/a:title", xmlString);
+    assertXpathNotExists("/a:entry/a:updated", xmlString);
+    assertXpathNotExists("/a:entry/a:category", xmlString);
+    assertXpathNotExists("/a:entry/a:link[@title=\"nr_Employees\"and @href=\"Rooms('1')/nr_Employees\"]", xmlString);
+    assertXpathNotExists("/a:entry/a:link[@title=\"nr_Building\"and @href=\"Rooms('1')/nr_Building\"]", xmlString);
+
+    assertXpathExists("/a:entry/a:content/m:properties/d:Name", xmlString);
+  }
+
+  @Test
+  public void contentOnlyRoomWithNavigationLink() throws Exception {
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+    Entity buildingLink = new Entity();
+    buildingLink.addProperty("Id", "1");
+    final EntitySerializerProperties properties =
+        EntitySerializerProperties.serviceRoot(BASE_URI).includeMetadata(false)
+            .build();
+
+    Entity localRoomData = new Entity();
+    localRoomData.addProperty("Name", "Neu Schwanstein");
+    localRoomData.addNavigation("nr_Building", buildingLink.getProperties());
+    localRoomData.setWriteProperties(properties);
+    AtomSerializerDeserializer ser = createAtomEntityProvider();
+    ODataResponse response = ser.writeEntry(entitySet, localRoomData);
+    String xmlString = verifyResponse(response);
+    assertXpathExists("/a:entry", xmlString);
+    assertXpathEvaluatesTo(BASE_URI.toASCIIString(), "/a:entry/@xml:base", xmlString);
+    assertXpathNotExists("/a:entry[@m:etag]", xmlString);
+
+    assertXpathNotExists("/a:entry/a:id", xmlString);
+    assertXpathNotExists("/a:entry/a:title", xmlString);
+    assertXpathNotExists("/a:entry/a:updated", xmlString);
+    assertXpathNotExists("/a:entry/a:category", xmlString);
+    assertXpathNotExists("/a:entry/a:link[@title=\"nr_Employees\"and @href=\"Rooms('1')/nr_Employees\"]", xmlString);
+
+    assertXpathExists("/a:entry/a:content/m:properties/d:Name", xmlString);
+    assertXpathExists("/a:entry/a:link[@title=\"nr_Building\"and @href=\"Buildings('1')\"]", xmlString);
+  }
+
+  @Test(expected=EntityProviderException.class)
+  public void contentOnlyRoomWithNavigationContent() throws Exception {
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+    Entity buildingLink = new Entity();
+    buildingLink.addProperty("Id", "1");
+    final EntitySerializerProperties properties =
+        EntitySerializerProperties.serviceRoot(BASE_URI).includeMetadata(true)
+            .build();
+
+    Entity localRoomData = new Entity();
+    localRoomData.addProperty("Name", "Neu Schwanstein");
+    localRoomData.addNavigation("nr_Building", buildingLink);
+    localRoomData.setWriteProperties(properties);
+    AtomSerializerDeserializer ser = createAtomEntityProvider();
+    ODataResponse response = ser.writeEntry(entitySet, localRoomData);
+    String xmlString = verifyResponse(response);
+    assertXpathExists("/a:entry", xmlString);
+    assertXpathEvaluatesTo(BASE_URI.toASCIIString(), "/a:entry/@xml:base", xmlString);
+    assertXpathNotExists("/a:entry[@m:etag]", xmlString);
+
+    assertXpathNotExists("/a:entry/a:id", xmlString);
+    assertXpathNotExists("/a:entry/a:title", xmlString);
+    assertXpathNotExists("/a:entry/a:updated", xmlString);
+    assertXpathNotExists("/a:entry/a:category", xmlString);
+    assertXpathNotExists("/a:entry/a:link[@title=\"nr_Employees\"and @href=\"Rooms('1')/nr_Employees\"]", xmlString);
+
+    assertXpathExists("/a:entry/a:content/m:properties/d:Name", xmlString);
+    assertXpathNotExists("/a:entry/a:link[@title=\"nr_Building\"and @href=\"Buildings('1')\"]", xmlString);
+  }
+  
+  @Test
+  public void contentOnlyRoomWithNavigationContentWithId() throws Exception {
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+    Entity buildingLink = new Entity();
+    buildingLink.addProperty("Id", "1");
+    final EntitySerializerProperties properties =
+        EntitySerializerProperties.serviceRoot(BASE_URI).includeMetadata(false)
+            .build();
+
+    Entity localRoomData = new Entity();
+    localRoomData.addProperty("Id", "1");
+    localRoomData.addProperty("Name", "Neu Schwanstein");
+    localRoomData.addNavigation("nr_Building", buildingLink);
+    localRoomData.setWriteProperties(properties);
+    AtomSerializerDeserializer ser = createAtomEntityProvider();
+    ODataResponse response = ser.writeEntry(entitySet, localRoomData);
+    String xmlString = verifyResponse(response);
+    assertXpathExists("/a:entry", xmlString);
+    assertXpathEvaluatesTo(BASE_URI.toASCIIString(), "/a:entry/@xml:base", xmlString);
+    assertXpathNotExists("/a:entry[@m:etag]", xmlString);
+
+    assertXpathNotExists("/a:entry/a:id", xmlString);
+    assertXpathNotExists("/a:entry/a:title", xmlString);
+    assertXpathNotExists("/a:entry/a:updated", xmlString);
+    assertXpathNotExists("/a:entry/a:category", xmlString);
+    assertXpathNotExists("/a:entry/a:link[@title=\"nr_Employees\"and @href=\"Rooms('1')/nr_Employees\"]", xmlString);
+
+    assertXpathExists("/a:entry/a:content/m:properties/d:Name", xmlString);
+    assertXpathNotExists("/a:entry/a:link[@title=\"nr_Building\"and @href=\"Buildings('1')\"]", xmlString);
+  }
+
+  @Test
+  public void contentOnlyWithoutKey() throws Exception {
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+    List<String> selectedPropertyNames = new ArrayList<String>();
+    selectedPropertyNames.add("ManagerId");
+
+    final EntitySerializerProperties properties =
+        EntitySerializerProperties.serviceRoot(BASE_URI).includeMetadata(false)
+            .build();
+
+    Entity localEmployeeData = new Entity();
+    localEmployeeData.addProperty("ManagerId", "1");
+    localEmployeeData.setWriteProperties(properties);
+
+    AtomSerializerDeserializer ser = createAtomEntityProvider();
+    ODataResponse response =
+        ser.writeEntry(entitySet, localEmployeeData);
+    String xmlString = verifyResponse(response);
+    assertXpathExists("/a:entry", xmlString);
+    assertXpathEvaluatesTo(BASE_URI.toASCIIString(), "/a:entry/@xml:base", xmlString);
+    assertXpathNotExists("/a:entry[@m:etag]", xmlString);
+
+    assertXpathNotExists("/a:entry/a:id", xmlString);
+    assertXpathNotExists("/a:entry/a:title", xmlString);
+    assertXpathNotExists("/a:entry/a:updated", xmlString);
+    assertXpathNotExists("/a:entry/a:category", xmlString);
+    assertXpathNotExists("/a:entry/a:link[@title=\"ne_Manager\"]", xmlString);
+    assertXpathNotExists("/a:entry/a:link[@title=\"ne_Team\"]", xmlString);
+    assertXpathNotExists("/a:entry/a:link[@title=\"ne_Room\"]", xmlString);
+    assertXpathNotExists("/a:entry/a:content", xmlString);
+
+    assertXpathExists("/a:entry/m:properties", xmlString);
+    assertXpathNotExists("/a:entry/m:properties/d:EmployeeId", xmlString);
+    assertXpathExists("/a:entry/m:properties/d:ManagerId", xmlString);
+  }
+
+  
+  @Test
+  public void contentOnlyWithNavigationLink() throws Exception {
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+    List<String> selectedPropertyNames = new ArrayList<String>();
+    selectedPropertyNames.add("ManagerId");
+    Entity managerLink = new Entity();
+    managerLink.addProperty("EmployeeId", "1");
+    final EntitySerializerProperties properties =
+        EntitySerializerProperties.serviceRoot(BASE_URI).includeMetadata(false)
+            .build();
+
+    Entity localEmployeeData = new Entity();
+    localEmployeeData.addProperty("ManagerId", "1");
+    localEmployeeData.addNavigation("ne_Manager", managerLink.getProperties());
+    localEmployeeData.setWriteProperties(properties);
+    AtomSerializerDeserializer ser = createAtomEntityProvider();
+    ODataResponse response =
+        ser.writeEntry(entitySet, localEmployeeData);
+    String xmlString = verifyResponse(response);
+    assertXpathExists("/a:entry", xmlString);
+    assertXpathEvaluatesTo(BASE_URI.toASCIIString(), "/a:entry/@xml:base", xmlString);
+    assertXpathNotExists("/a:entry[@m:etag]", xmlString);
+
+    assertXpathNotExists("/a:entry/a:id", xmlString);
+    assertXpathNotExists("/a:entry/a:title", xmlString);
+    assertXpathNotExists("/a:entry/a:updated", xmlString);
+    assertXpathNotExists("/a:entry/a:category", xmlString);
+    assertXpathNotExists("/a:entry/a:link[@title=\"ne_Team\"]", xmlString);
+    assertXpathNotExists("/a:entry/a:link[@title=\"ne_Room\"]", xmlString);
+    assertXpathNotExists("/a:entry/a:content", xmlString);
+
+    assertXpathExists("/a:entry/m:properties", xmlString);
+    assertXpathNotExists("/a:entry/m:properties/d:EmployeeId", xmlString);
+    assertXpathExists("/a:entry/m:properties/d:ManagerId", xmlString);
+
+    assertXpathExists("/a:entry/a:link[@href=\"Managers('1')\" and @title=\"ne_Manager\"]", xmlString);
+  }
+
+  @Test
+  public void noneSyndicationKeepInContentFalseMustNotShowInProperties() throws Exception {
+    // prepare Mock
+    EdmEntitySet employeesSet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+    EdmCustomizableFeedMappings employeeCustomPropertyMapping = mock(EdmCustomizableFeedMappings.class);
+    when(employeeCustomPropertyMapping.isFcKeepInContent()).thenReturn(Boolean.FALSE);
+    when(employeeCustomPropertyMapping.getFcNsPrefix()).thenReturn("customPre");
+    when(employeeCustomPropertyMapping.getFcNsUri()).thenReturn("http://customUri.com");
+    EdmTyped employeeEntryDateProperty = employeesSet.getEntityType().getProperty("EmployeeName");
+    when(((EdmProperty) employeeEntryDateProperty).getCustomizableFeedMappings()).thenReturn(
+        employeeCustomPropertyMapping);
+
+    Map<String, String> prefixMap = new HashMap<String, String>();
+    prefixMap.put("a", Edm.NAMESPACE_ATOM_2005);
+    prefixMap.put("d", Edm.NAMESPACE_D_2007_08);
+    prefixMap.put("m", Edm.NAMESPACE_M_2007_08);
+    prefixMap.put("xml", Edm.NAMESPACE_XML_1998);
+    prefixMap.put("customPre", "http://customUri.com");
+    XMLUnit.setXpathNamespaceContext(new SimpleNamespaceContext(prefixMap));
+    employeeData.setWriteProperties(DEFAULT_PROPERTIES);
+
+    AtomSerializerDeserializer ser = createAtomEntityProvider();
+    ODataResponse response = ser.writeEntry(employeesSet, employeeData);
+    String xmlString = verifyResponse(response);
+
+    assertXpathExists("/a:entry/customPre:EmployeeName", xmlString);
+    assertXpathNotExists("/a:entry/m:properties/d:EmployeeName", xmlString);
+  }
+
+  @Test
+  public void noneSyndicationKeepInContentTrueMustShowInProperties() throws Exception {
+    // prepare Mock
+    EdmEntitySet employeesSet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+    EdmCustomizableFeedMappings employeeCustomPropertyMapping = mock(EdmCustomizableFeedMappings.class);
+    when(employeeCustomPropertyMapping.isFcKeepInContent()).thenReturn(Boolean.TRUE);
+    when(employeeCustomPropertyMapping.getFcNsPrefix()).thenReturn("customPre");
+    when(employeeCustomPropertyMapping.getFcNsUri()).thenReturn("http://customUri.com");
+    EdmTyped employeeEntryDateProperty = employeesSet.getEntityType().getProperty("EmployeeName");
+    when(((EdmProperty) employeeEntryDateProperty).getCustomizableFeedMappings()).thenReturn(
+        employeeCustomPropertyMapping);
+
+    Map<String, String> prefixMap = new HashMap<String, String>();
+    prefixMap.put("a", Edm.NAMESPACE_ATOM_2005);
+    prefixMap.put("d", Edm.NAMESPACE_D_2007_08);
+    prefixMap.put("m", Edm.NAMESPACE_M_2007_08);
+    prefixMap.put("xml", Edm.NAMESPACE_XML_1998);
+    prefixMap.put("customPre", "http://customUri.com");
+    XMLUnit.setXpathNamespaceContext(new SimpleNamespaceContext(prefixMap));
+    employeeData.setWriteProperties(DEFAULT_PROPERTIES);
+
+    AtomSerializerDeserializer ser = createAtomEntityProvider();
+    ODataResponse response = ser.writeEntry(employeesSet, employeeData);
+    String xmlString = verifyResponse(response);
+
+    assertXpathExists("/a:entry/customPre:EmployeeName", xmlString);
+    assertXpathExists("/a:entry/m:properties/d:EmployeeName", xmlString);
+  }
+
+  @Test
+  public void noneSyndicationWithNullPrefix() throws Exception {
+    // prepare Mock
+    EdmEntitySet employeesSet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+    EdmCustomizableFeedMappings employeeCustomPropertyMapping = mock(EdmCustomizableFeedMappings.class);
+    when(employeeCustomPropertyMapping.isFcKeepInContent()).thenReturn(Boolean.TRUE);
+    when(employeeCustomPropertyMapping.getFcNsUri()).thenReturn("http://customUri.com");
+    EdmTyped employeeEntryDateProperty = employeesSet.getEntityType().getProperty("EmployeeName");
+    when(((EdmProperty) employeeEntryDateProperty).getCustomizableFeedMappings()).thenReturn(
+        employeeCustomPropertyMapping);
+
+    Map<String, String> prefixMap = new HashMap<String, String>();
+    prefixMap.put("a", Edm.NAMESPACE_ATOM_2005);
+    prefixMap.put("d", Edm.NAMESPACE_D_2007_08);
+    prefixMap.put("m", Edm.NAMESPACE_M_2007_08);
+    prefixMap.put("xml", Edm.NAMESPACE_XML_1998);
+    prefixMap.put("customPre", "http://customUri.com");
+    XMLUnit.setXpathNamespaceContext(new SimpleNamespaceContext(prefixMap));
+
+    AtomSerializerDeserializer ser = createAtomEntityProvider();
+    employeeData.setWriteProperties(DEFAULT_PROPERTIES);
+    boolean thrown = false;
+    try {
+      ser.writeEntry(employeesSet, employeeData);
+    } catch (EntityProviderException e) {
+      verifyRootCause(EntityProviderProducerException.class, EntityProviderException.INVALID_NAMESPACE.getKey(), e);
+      thrown = true;
+    }
+    if (!thrown) {
+      fail("Exception should have been thrown");
+    }
+  }
+
+  @Test
+  public void noneSyndicationWithNullUri() throws Exception {
+    // prepare Mock
+    EdmEntitySet employeesSet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+    EdmCustomizableFeedMappings employeeCustomPropertyMapping = mock(EdmCustomizableFeedMappings.class);
+    when(employeeCustomPropertyMapping.isFcKeepInContent()).thenReturn(Boolean.TRUE);
+    when(employeeCustomPropertyMapping.getFcNsPrefix()).thenReturn("customPre");
+    EdmTyped employeeEntryDateProperty = employeesSet.getEntityType().getProperty("EmployeeName");
+    when(((EdmProperty) employeeEntryDateProperty).getCustomizableFeedMappings()).thenReturn(
+        employeeCustomPropertyMapping);
+
+    Map<String, String> prefixMap = new HashMap<String, String>();
+    prefixMap.put("a", Edm.NAMESPACE_ATOM_2005);
+    prefixMap.put("d", Edm.NAMESPACE_D_2007_08);
+    prefixMap.put("m", Edm.NAMESPACE_M_2007_08);
+    prefixMap.put("xml", Edm.NAMESPACE_XML_1998);
+    prefixMap.put("customPre", "http://customUri.com");
+    XMLUnit.setXpathNamespaceContext(new SimpleNamespaceContext(prefixMap));
+
+    AtomSerializerDeserializer ser = createAtomEntityProvider();
+    employeeData.setWriteProperties(DEFAULT_PROPERTIES);
+    boolean thrown = false;
+    try {
+      ser.writeEntry(employeesSet, employeeData);
+    } catch (EntityProviderException e) {
+      verifyRootCause(EntityProviderProducerException.class, EntityProviderException.INVALID_NAMESPACE.getKey(), e);
+      thrown = true;
+    }
+    if (!thrown) {
+      fail("Exception should have been thrown");
+    }
+  }
+
+  @Test
+  public void noneSyndicationWithNullUriAndNullPrefix() throws Exception {
+    // prepare Mock
+    EdmEntitySet employeesSet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+    EdmCustomizableFeedMappings employeeCustomPropertyMapping = mock(EdmCustomizableFeedMappings.class);
+    when(employeeCustomPropertyMapping.isFcKeepInContent()).thenReturn(Boolean.TRUE);
+    EdmTyped employeeEntryDateProperty = employeesSet.getEntityType().getProperty("EmployeeName");
+    when(((EdmProperty) employeeEntryDateProperty).getCustomizableFeedMappings()).thenReturn(
+        employeeCustomPropertyMapping);
+
+    Map<String, String> prefixMap = new HashMap<String, String>();
+    prefixMap.put("a", Edm.NAMESPACE_ATOM_2005);
+    prefixMap.put("d", Edm.NAMESPACE_D_2007_08);
+    prefixMap.put("m", Edm.NAMESPACE_M_2007_08);
+    prefixMap.put("xml", Edm.NAMESPACE_XML_1998);
+    prefixMap.put("f", "http://customUri.com");
+    XMLUnit.setXpathNamespaceContext(new SimpleNamespaceContext(prefixMap));
+
+    AtomSerializerDeserializer ser = createAtomEntityProvider();
+    employeeData.setWriteProperties(DEFAULT_PROPERTIES);
+    boolean thrown = false;
+    try {
+      ser.writeEntry(employeesSet, employeeData);
+    } catch (EntityProviderException e) {
+      verifyRootCause(EntityProviderProducerException.class, EntityProviderException.INVALID_NAMESPACE.getKey(), e);
+      thrown = true;
+    }
+    if (!thrown) {
+      fail("Exception should have been thrown");
+    }
+  }
+
+  @Test
+  public void syndicationWithComplexProperty() throws Exception {
+    // prepare Mock
+    EdmEntitySet employeesSet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+    EdmCustomizableFeedMappings employeeCustomPropertyMapping = mock(EdmCustomizableFeedMappings.class);
+    when(employeeCustomPropertyMapping.isFcKeepInContent()).thenReturn(Boolean.TRUE);
+    when(employeeCustomPropertyMapping.getFcNsPrefix()).thenReturn("customPre");
+    when(employeeCustomPropertyMapping.getFcNsUri()).thenReturn("http://customUri.com");
+    EdmTyped employeeLocationProperty = employeesSet.getEntityType().getProperty("Location");
+    when(((EdmProperty) employeeLocationProperty).getCustomizableFeedMappings()).thenReturn(
+        employeeCustomPropertyMapping);
+
+    Map<String, String> prefixMap = new HashMap<String, String>();
+    prefixMap.put("a", Edm.NAMESPACE_ATOM_2005);
+    prefixMap.put("d", Edm.NAMESPACE_D_2007_08);
+    prefixMap.put("m", Edm.NAMESPACE_M_2007_08);
+    prefixMap.put("xml", Edm.NAMESPACE_XML_1998);
+    prefixMap.put("customPre", "http://customUri.com");
+    XMLUnit.setXpathNamespaceContext(new SimpleNamespaceContext(prefixMap));
+    employeeData.setWriteProperties(DEFAULT_PROPERTIES);
+
+    AtomSerializerDeserializer ser = createAtomEntityProvider();
+    ODataResponse response = ser.writeEntry(employeesSet, employeeData);
+    String xmlString = verifyResponse(response);
+
+    assertXpathNotExists("/a:entry/customPre:Location", xmlString);
+    assertXpathExists("/a:entry/m:properties/d:Location", xmlString);
+  }
+
+  private void verifyRootCause(final Class<?> class1, final String key, final ODataMessageException e) {
+
+    Throwable thrownException = e;
+    Throwable lastFoundException = null;
+    if (e.getClass().equals(class1)) {
+      lastFoundException = e;
+    }
+
+    while (thrownException.getCause() != null) {
+      thrownException = thrownException.getCause();
+      if (thrownException.getClass().equals(class1)) {
+        lastFoundException = thrownException;
+      }
+    }
+
+    if (lastFoundException != null) {
+      ODataMessageException msgException = (ODataMessageException) lastFoundException;
+      assertEquals(key, msgException.getMessageReference().getKey());
+    } else {
+      fail("Exception of class: " + class1.getCanonicalName() + " in stacktrace not found.");
+    }
+  }
+
+  @Test
+  public void serializeAtomMediaResource() throws IOException, XpathException, SAXException, XMLStreamException,
+      FactoryConfigurationError, ODataException {
+    AtomSerializerDeserializer ser = createAtomEntityProvider();
+    employeeData.setWriteProperties(DEFAULT_PROPERTIES);
+    ODataResponse response =
+        ser.writeEntry(MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees"), employeeData);
+    String xmlString = verifyResponse(response);
+
+    assertXpathExists("/a:entry", xmlString);
+    assertXpathEvaluatesTo(BASE_URI.toASCIIString(), "/a:entry/@xml:base", xmlString);
+
+    assertXpathExists("/a:entry/a:content", xmlString);
+    assertXpathEvaluatesTo("", "/a:entry/a:content", xmlString);
+    assertXpathEvaluatesTo(ContentType.APPLICATION_OCTET_STREAM.toString(), "/a:entry/a:content/@type", xmlString);
+    assertXpathEvaluatesTo("Employees('1')/$value", "/a:entry/a:content/@src", xmlString);
+    assertXpathExists("/a:entry/m:properties", xmlString);
+
+    assertXpathExists("/a:entry/a:link[@href=\"Employees('1')/$value\"]", xmlString);
+    assertXpathExists("/a:entry/a:link[@rel='edit-media']", xmlString);
+    assertXpathExists("/a:entry/a:link[@type='application/octet-stream']", xmlString);
+
+    assertXpathExists("/a:entry/a:link[@href=\"Employees('1')\"]", xmlString);
+    assertXpathExists("/a:entry/a:link[@rel='edit']", xmlString);
+    assertXpathExists("/a:entry/a:link[@title='Employee']", xmlString);
+
+    verifyTagOrdering(xmlString,
+        "link((?:(?!link).)*?)edit",
+        "link((?:(?!link).)*?)edit-media");
+  }
+
+  private String verifyResponse(final ODataResponse response) throws IOException {
+    assertNotNull(response);
+    assertNotNull(response.getEntity());
+    assertNull("EntityProvider should not set content header", response.getContentHeader());
+    String xmlString = StringHelper.inputStreamToString((InputStream) response.getEntity());
+    return xmlString;
+  }
+
+  @Test
+  public void serializeAtomMediaResourceWithMimeType() throws IOException, XpathException, SAXException,
+      XMLStreamException, FactoryConfigurationError, ODataException {
+    AtomSerializerDeserializer ser = createAtomEntityProvider();
+    EntitySerializerProperties properties = EntitySerializerProperties.serviceRoot(BASE_URI)
+        .includeMetadata(true).build();
+    Entity localEmployeeData = new Entity();
+
+    Calendar date = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
+    date.clear();
+    date.set(1999, 0, 1);
+
+    localEmployeeData.addProperty("EmployeeId", "1");
+    localEmployeeData.addProperty("ImmageUrl", null);
+    localEmployeeData.addProperty("ManagerId", "1");
+    localEmployeeData.addProperty("Age", new Integer(52));
+    localEmployeeData.addProperty("RoomId", "1");
+    localEmployeeData.addProperty("EntryDate", date);
+    localEmployeeData.addProperty("TeamId", "42");
+    localEmployeeData.addProperty("EmployeeName", "Walter Winter");
+    localEmployeeData.addProperty("getImageType", "abc");
+
+    Entity locationData = new Entity();
+    Entity cityData = new Entity();
+    cityData.addProperty("PostalCode", "33470");
+    cityData.addProperty("CityName", "Duckburg");
+    locationData.addProperty("City", cityData);
+    locationData.addProperty("Country", "Calisota");
+
+    localEmployeeData.addProperty("Location", locationData);
+    localEmployeeData.setWriteProperties(properties);
+    ODataResponse response =
+        ser.writeEntry(MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees"),
+            localEmployeeData);
+    String xmlString = verifyResponse(response);
+
+    assertXpathExists("/a:entry", xmlString);
+    assertXpathEvaluatesTo(BASE_URI.toASCIIString(), "/a:entry/@xml:base", xmlString);
+
+    assertXpathExists("/a:entry/a:content", xmlString);
+    assertXpathEvaluatesTo("abc", "/a:entry/a:content/@type", xmlString);
+    assertXpathEvaluatesTo("Employees('1')/$value", "/a:entry/a:content/@src", xmlString);
+    assertXpathExists("/a:entry/m:properties", xmlString);
+  }
+
+  /*
+   * * Test serialization of empty syndication title property. EmployeeName is set to NULL after the update (which is
+   * allowed because EmployeeName has default Nullable behavior which is true).
+   * Write of an empty atom title tag is allowed within RFC4287 (http://tools.ietf.org/html/rfc4287#section-4.2.14).
+   **/
+  @Test
+  public void serializeEmployeeWithNullSyndicationTitleProperty() throws IOException, XpathException, SAXException,
+      XMLStreamException, FactoryConfigurationError, ODataException {
+    AtomSerializerDeserializer ser = createAtomEntityProvider();
+    EntitySerializerProperties properties = EntitySerializerProperties.serviceRoot(BASE_URI)
+        .includeMetadata(true).build();
+    employeeData.addProperty("EmployeeName", null);
+    employeeData.setWriteProperties(properties);
+    ODataResponse response =
+        ser.writeEntry(MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees"), employeeData);
+    String xmlString = verifyResponse(response);
+
+    assertXpathExists("/a:entry/a:title", xmlString);
+    assertXpathEvaluatesTo("", "/a:entry/a:title", xmlString);
+
+    assertXpathExists("/a:entry", xmlString);
+    assertXpathEvaluatesTo(BASE_URI.toASCIIString(), "/a:entry/@xml:base", xmlString);
+
+    assertXpathExists("/a:entry/a:content", xmlString);
+    assertXpathEvaluatesTo("Employees('1')/$value", "/a:entry/a:content/@src", xmlString);
+    assertXpathExists("/a:entry/m:properties", xmlString);
+  }
+
+  @Test
+  public void serializeEmployeeAndCheckOrderOfTags() throws IOException, XpathException, SAXException,
+      XMLStreamException, FactoryConfigurationError, ODataException {
+    AtomSerializerDeserializer ser = createAtomEntityProvider();
+    EntitySerializerProperties properties = EntitySerializerProperties.serviceRoot(BASE_URI)
+        .includeMetadata(true).build();
+    Entity localEmployeeData = new Entity();
+
+    Calendar date = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
+    date.clear();
+    date.set(1999, 0, 1);
+
+    localEmployeeData.addProperty("EmployeeId", "1");
+    localEmployeeData.addProperty("ImmageUrl", null);
+    localEmployeeData.addProperty("ManagerId", "1");
+    localEmployeeData.addProperty("Age", new Integer(52));
+    localEmployeeData.addProperty("RoomId", "1");
+    localEmployeeData.addProperty("EntryDate", date);
+    localEmployeeData.addProperty("TeamId", "42");
+    localEmployeeData.addProperty("EmployeeName", "Walter Winter");
+    localEmployeeData.addProperty("getImageType", "abc");
+
+    Entity locationData = new Entity();
+    Entity cityData = new Entity();
+    cityData.addProperty("PostalCode", "33470");
+    cityData.addProperty("CityName", "Duckburg");
+    cityData.setWriteProperties(properties);
+    locationData.addProperty("City", cityData);
+    locationData.addProperty("Country", "Calisota");
+    locationData.setWriteProperties(properties);
+    localEmployeeData.setWriteProperties(properties);
+
+    localEmployeeData.addProperty("Location", locationData);
+    ODataResponse response =
+        ser.writeEntry(MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees"),
+            localEmployeeData);
+    String xmlString = verifyResponse(response);
+
+    assertXpathExists("/a:entry", xmlString);
+    assertXpathExists("/a:entry/a:content", xmlString);
+    // verify self link
+    assertXpathExists("/a:entry/a:link[@href=\"Employees('1')\"]", xmlString);
+    // verify content media link
+    assertXpathExists("/a:entry/a:link[@href=\"Employees('1')/$value\"]", xmlString);
+    // verify one navigation link
+    assertXpathNotExists("/a:entry/a:link[@title='ne_Manager']", xmlString);
+
+    // verify content
+    assertXpathExists("/a:entry/a:content[@type='abc']", xmlString);
+    // verify properties
+    assertXpathExists("/a:entry/m:properties", xmlString);
+    assertXpathEvaluatesTo("8", "count(/a:entry/m:properties/*)", xmlString);
+
+    // verify order of tags
+    verifyTagOrdering(xmlString, "id", "title", "updated", "category",
+        "link((?:(?!link).)*?)edit",
+        "link((?:(?!link).)*?)edit-media",
+        "content", "properties");
+  }
+
+  @Test
+  public void serializeEmployeeAndCheckOrderOfPropertyTags() throws IOException, XpathException, SAXException,
+      XMLStreamException, FactoryConfigurationError, ODataException {
+    AtomSerializerDeserializer ser = createAtomEntityProvider();
+    EntitySerializerProperties properties =
+        EntitySerializerProperties.serviceRoot(BASE_URI).includeMetadata(true).build();
+    employeeData.setWriteProperties(properties);
+    EdmEntitySet employeeEntitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+    ODataResponse response = ser.writeEntry(employeeEntitySet, employeeData);
+    String xmlString = verifyResponse(response);
+
+    assertXpathExists("/a:entry", xmlString);
+    assertXpathExists("/a:entry/a:content", xmlString);
+    // verify properties
+    assertXpathExists("/a:entry/m:properties", xmlString);
+    assertXpathEvaluatesTo("8", "count(/a:entry/m:properties/*)", xmlString);
+
+    // verify order of tags
+    List<String> expectedPropertyNamesFromEdm = new ArrayList<String>(employeeEntitySet.getEntityType()
+        .getPropertyNames());
+    expectedPropertyNamesFromEdm.remove(String.valueOf("ImageUrl"));
+    verifyTagOrdering(xmlString, expectedPropertyNamesFromEdm.toArray(new String[0]));
+  }
+
+  @Test
+  public void serializeEmployeeAndCheckKeepInContentFalse() throws IOException, XpathException, SAXException,
+      XMLStreamException, FactoryConfigurationError, ODataException {
+    AtomSerializerDeserializer ser = createAtomEntityProvider();
+    EntitySerializerProperties properties =
+        EntitySerializerProperties.serviceRoot(BASE_URI).includeMetadata(true).build();
+    EdmEntitySet employeeEntitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+
+    // set "keepInContent" to false for EntryDate
+    EdmCustomizableFeedMappings employeeUpdatedMappings = mock(EdmCustomizableFeedMappings.class);
+    when(employeeUpdatedMappings.getFcTargetPath()).thenReturn(EdmTargetPath.SYNDICATION_UPDATED);
+    when(employeeUpdatedMappings.isFcKeepInContent()).thenReturn(Boolean.FALSE);
+    EdmTyped employeeEntryDateProperty = employeeEntitySet.getEntityType().getProperty("EntryDate");
+    when(((EdmProperty) employeeEntryDateProperty).getCustomizableFeedMappings()).thenReturn(employeeUpdatedMappings);
+    employeeData.setWriteProperties(properties);
+    ODataResponse response = ser.writeEntry(employeeEntitySet, employeeData);
+    String xmlString = verifyResponse(response);
+
+    assertXpathExists("/a:entry", xmlString);
+    assertXpathExists("/a:entry/a:content", xmlString);
+    // verify properties
+    assertXpathExists("/a:entry/m:properties", xmlString);
+    assertXpathEvaluatesTo("7", "count(/a:entry/m:properties/*)", xmlString);
+    //
+    assertXpathNotExists("/a:entry/m:properties/d:EntryDate", xmlString);
+
+    // verify order of tags
+    List<String> expectedPropertyNamesFromEdm =
+        new ArrayList<String>(employeeEntitySet.getEntityType().getPropertyNames());
+    expectedPropertyNamesFromEdm.remove(String.valueOf("EntryDate"));
+    expectedPropertyNamesFromEdm.remove(String.valueOf("ImageUrl"));
+    verifyTagOrdering(xmlString, expectedPropertyNamesFromEdm.toArray(new String[0]));
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void serializeAtomEntryWithNullData() throws IOException, XpathException, SAXException, XMLStreamException,
+      FactoryConfigurationError, ODataException {
+    final EntitySerializerProperties properties =
+        EntitySerializerProperties.serviceRoot(BASE_URI).build();
+    AtomSerializerDeserializer ser = createAtomEntityProvider();
+    roomData.setWriteProperties(properties);
+    ser.writeEntry(MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms"), null);
+  }
+
+  @Test
+  public void serializeAtomEntryWithEmptyEntity() throws IOException, XpathException, SAXException,
+      XMLStreamException, FactoryConfigurationError, ODataException {
+    final EntitySerializerProperties properties =
+        EntitySerializerProperties.serviceRoot(BASE_URI).includeMetadata(false).build();
+    AtomSerializerDeserializer ser = createAtomEntityProvider();
+    Entity entity = new Entity();
+    entity.setWriteProperties(properties);
+     ODataResponse response = ser.writeEntry(MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms"),
+        entity);
+     String xmlString = verifyResponse(response);
+    assertXpathEvaluatesTo(BASE_URI.toASCIIString(), "/a:entry/@xml:base", xmlString);
+
+    assertXpathExists("/a:entry/a:content", xmlString);
+    assertXpathEvaluatesTo(ContentType.APPLICATION_XML.toString(), "/a:entry/a:content/@type", xmlString);
+
+ 
+  }
+
+  @Test
+  public void serializeAtomEntry() throws IOException, XpathException, SAXException, XMLStreamException,
+      FactoryConfigurationError, ODataException {
+    final EntitySerializerProperties properties =
+        EntitySerializerProperties.serviceRoot(BASE_URI).build();
+    AtomSerializerDeserializer ser = createAtomEntityProvider();
+    roomData.setWriteProperties(properties);
+    ODataResponse response =
+        ser.writeEntry(MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms"), roomData);
+    String xmlString = verifyResponse(response);
+
+    assertXpathExists("/a:entry", xmlString);
+    assertXpathEvaluatesTo(BASE_URI.toASCIIString(), "/a:entry/@xml:base", xmlString);
+
+    assertXpathExists("/a:entry/a:content", xmlString);
+    assertXpathEvaluatesTo(ContentType.APPLICATION_XML.toString(), "/a:entry/a:content/@type", xmlString);
+
+    assertXpathExists("/a:entry/a:content/m:properties", xmlString);
+  }
+
+  @Test
+  public void serializeEntryId() throws IOException, XpathException, SAXException, XMLStreamException,
+      FactoryConfigurationError, ODataException {
+    AtomSerializerDeserializer ser = createAtomEntityProvider();
+    employeeData.setWriteProperties(DEFAULT_PROPERTIES);
+    ODataResponse response =
+        ser.writeEntry(MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees"), employeeData);
+    String xmlString = verifyResponse(response);
+
+    assertXpathExists("/a:entry", xmlString);
+    assertXpathEvaluatesTo(BASE_URI.toASCIIString(), "/a:entry/@xml:base", xmlString);
+    assertXpathExists("/a:entry/a:id", xmlString);
+    assertXpathEvaluatesTo(BASE_URI.toASCIIString() + "Employees('1')", "/a:entry/a:id/text()", xmlString);
+  }
+
+  @Test
+  public void serializeEntryTitle() throws Exception {
+    AtomSerializerDeserializer ser = createAtomEntityProvider();
+    employeeData.setWriteProperties(DEFAULT_PROPERTIES);
+    ODataResponse response =
+        ser.writeEntry(MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees"), employeeData);
+    String xmlString = verifyResponse(response);
+
+    assertXpathExists("/a:entry/a:title", xmlString);
+    assertXpathEvaluatesTo("text", "/a:entry/a:title/@type", xmlString);
+    assertXpathEvaluatesTo((String) employeeData.getProperty("EmployeeName"), "/a:entry/a:title/text()", xmlString);
+  }
+
+  @Test
+  public void serializeEntryUpdated() throws Exception {
+    AtomSerializerDeserializer ser = createAtomEntityProvider();
+    employeeData.setWriteProperties(DEFAULT_PROPERTIES);
+    ODataResponse response =
+        ser.writeEntry(MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees"), employeeData);
+    String xmlString = verifyResponse(response);
+
+    assertXpathExists("/a:entry/a:updated", xmlString);
+    assertXpathEvaluatesTo("1999-01-01T00:00:00Z", "/a:entry/a:updated/text()", xmlString);
+  }
+
+  @Test
+  public void serializeIds() throws IOException, XpathException, SAXException, XMLStreamException,
+      FactoryConfigurationError, ODataException {
+    AtomSerializerDeserializer ser = createAtomEntityProvider();
+    photoData.setWriteProperties(DEFAULT_PROPERTIES);
+    ODataResponse response =
+        ser.writeEntry(MockFacade.getMockEdm().getEntityContainer("Container2").getEntitySet("Photos"), photoData);
+    String xmlString = verifyResponse(response);
+
+    assertXpathExists("/a:entry", xmlString);
+    assertXpathEvaluatesTo(BASE_URI.toASCIIString(), "/a:entry/@xml:base", xmlString);
+    assertXpathExists("/a:entry/a:id", xmlString);
+    assertXpathEvaluatesTo(BASE_URI.toASCIIString() + "Container2.Photos(Id=1,Type='image%2Fpng')",
+        "/a:entry/a:id/text()", xmlString);
+  }
+
+  @Test
+  public void serializeProperties() throws IOException, XpathException, SAXException, XMLStreamException,
+      FactoryConfigurationError, ODataException {
+    AtomSerializerDeserializer ser = createAtomEntityProvider();
+    employeeData.setWriteProperties(DEFAULT_PROPERTIES);
+    ODataResponse response =
+        ser.writeEntry(MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees"), employeeData);
+    String xmlString = verifyResponse(response);
+
+    assertXpathExists("/a:entry/m:properties", xmlString);
+    assertXpathEvaluatesTo((String) employeeData.getProperty("RoomId"), "/a:entry/m:properties/d:RoomId/text()",
+        xmlString);
+    assertXpathEvaluatesTo((String) employeeData.getProperty("TeamId"), "/a:entry/m:properties/d:TeamId/text()",
+        xmlString);
+  }
+
+  
+   @Test
+   public void serializeWithValueEncoding() throws IOException, XpathException, SAXException, XMLStreamException,
+    FactoryConfigurationError, ODataException {
+    photoData.addProperty("Type", "< Ö >");
+    photoData.setWriteProperties(DEFAULT_PROPERTIES);
+    
+    AtomSerializerDeserializer ser = createAtomEntityProvider();
+    ODataResponse response =
+    ser.writeEntry(MockFacade.getMockEdm().getEntityContainer("Container2").getEntitySet("Photos"), photoData);
+    String xmlString = verifyResponse(response);
+    
+    assertXpathExists("/a:entry", xmlString);
+    assertXpathEvaluatesTo(BASE_URI.toASCIIString(), "/a:entry/@xml:base", xmlString);
+    assertXpathExists("/a:entry/a:id", xmlString);
+    assertXpathEvaluatesTo(BASE_URI.toASCIIString() + "Container2.Photos(Id=1,Type='%3C%20%C3%96%20%3E')",
+    "/a:entry/a:id/text()", xmlString);
+    assertXpathEvaluatesTo("Container2.Photos(Id=1,Type='%3C%20%C3%96%20%3E')", "/a:entry/a:link/@href", xmlString);
+    }
+   
+
+  @Test
+  public void serializeCategory() throws IOException, XpathException, SAXException, XMLStreamException,
+      FactoryConfigurationError, ODataException {
+    AtomSerializerDeserializer ser = createAtomEntityProvider();
+    employeeData.setWriteProperties(DEFAULT_PROPERTIES);
+    ODataResponse response =
+        ser.writeEntry(MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees"), employeeData);
+    String xmlString = verifyResponse(response);
+
+    assertXpathExists("/a:entry/a:category", xmlString);
+    assertXpathExists("/a:entry/a:category/@term", xmlString);
+    assertXpathExists("/a:entry/a:category/@scheme", xmlString);
+    assertXpathEvaluatesTo("RefScenario.Employee", "/a:entry/a:category/@term", xmlString);
+    assertXpathEvaluatesTo(Edm.NAMESPACE_SCHEME_2007_08, "/a:entry/a:category/@scheme", xmlString);
+  }   
+
+
+  @Test(expected = EntityProviderException.class)
+  public void serializeWithFacetsValidation() throws Exception {
+    Edm edm = MockFacade.getMockEdm();
+    EdmTyped roomNameProperty = edm.getEntityType("RefScenario", "Room").getProperty("Name");
+    EdmFacets facets = mock(EdmFacets.class);
+    when(facets.getMaxLength()).thenReturn(3);
+    when(((EdmProperty) roomNameProperty).getFacets()).thenReturn(facets);
+
+    roomData.addProperty("Name", "1234567");
+    roomData.setWriteProperties(DEFAULT_PROPERTIES);
+    AtomSerializerDeserializer ser = createAtomEntityProvider();
+    ODataResponse response =
+        ser.writeEntry(edm.getDefaultEntityContainer().getEntitySet("Rooms"), roomData);
+    Assert.assertNotNull(response);
+  }
+
+  @Test
+  public void serializeWithoutFacetsValidation() throws Exception {
+    Edm edm = MockFacade.getMockEdm();
+    EdmTyped roomNameProperty = edm.getEntityType("RefScenario", "Room").getProperty("Name");
+    EdmFacets facets = mock(EdmFacets.class);
+    when(facets.getMaxLength()).thenReturn(3);
+    when(((EdmProperty) roomNameProperty).getFacets()).thenReturn(facets);
+
+    String name = "1234567";
+    roomData.addProperty("Name", name);
+    AtomSerializerDeserializer ser = createAtomEntityProvider();
+    EntitySerializerProperties properties = EntitySerializerProperties
+        .fromProperties(DEFAULT_PROPERTIES).validatingFacets(false).build();
+    roomData.setWriteProperties(properties);
+    ODataResponse response =
+        ser.writeEntry(edm.getDefaultEntityContainer().getEntitySet("Rooms"), roomData);
+    assertNotNull(response);
+
+    assertNotNull(response.getEntity());
+    String xmlString = StringHelper.inputStreamToString((InputStream) response.getEntity());
+
+    assertXpathEvaluatesTo(name, "/a:entry/a:content/m:properties/d:Name/text()", xmlString);
+  }
+
+  @Test
+  public void serializeCustomMapping() throws IOException, XpathException, SAXException, XMLStreamException,
+    FactoryConfigurationError, ODataException {
+    AtomSerializerDeserializer ser = createAtomEntityProvider();
+    photoData.setWriteProperties(DEFAULT_PROPERTIES);
+    ODataResponse response =
+    ser.writeEntry(MockFacade.getMockEdm().getEntityContainer("Container2").getEntitySet("Photos"), photoData);
+    String xmlString = verifyResponse(response);
+    
+    assertXpathExists("/a:entry", xmlString);
+    assertXpathExists("/a:entry/custom:CustomProperty", xmlString);
+    //assertXpathExists("/a:entry/ру:Содержание", xmlString);
+  //TODO  
+    //assertXpathEvaluatesTo((String) photoData.getProperty("Содержание"), 
+    //"/a:entry/ру:Содержание/text()", xmlString);
+    verifyTagOrdering(xmlString, "category", "Содержание", "content", "properties");
+ }
+   
+  @Test
+  public void testCustomProperties() throws Exception {
+   AtomSerializerDeserializer ser = createAtomEntityProvider();
+   EdmEntitySet entitySet = MockFacade.getMockEdm().getEntityContainer("Container2").getEntitySet("Photos");
+   photoData.setWriteProperties(DEFAULT_PROPERTIES);
+   ODataResponse response = ser.writeEntry(entitySet, photoData );
+   String xmlString = verifyResponse(response);
+    
+   assertXpathExists("/a:entry", xmlString);
+   assertXpathExists("/a:entry/custom:CustomProperty", xmlString);
+   assertXpathNotExists("/a:entry/custom:CustomProperty/text()", xmlString);
+   assertXpathEvaluatesTo("true", "/a:entry/custom:CustomProperty/@m:null", xmlString);
+   verifyTagOrdering(xmlString, "category", "Содержание", "CustomProperty", "content", "properties");
+  }
+   
+
+  
+  @Test
+  public void testKeepInContentNull() throws Exception {
+    AtomSerializerDeserializer ser = createAtomEntityProvider();
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getEntityContainer("Container2").getEntitySet("Photos");
+    
+    EdmProperty customProperty = (EdmProperty) entitySet.getEntityType().getProperty("CustomProperty");
+    when(customProperty.getCustomizableFeedMappings().isFcKeepInContent()).thenReturn(null);
+    photoData.setWriteProperties(DEFAULT_PROPERTIES);
+    
+    ODataResponse response = ser.writeEntry(entitySet, photoData);
+    String xmlString = verifyResponse(response);
+    
+    assertXpathExists("/a:entry", xmlString);
+    assertXpathExists("/a:entry/custom:CustomProperty", xmlString);
+    assertXpathNotExists("/a:entry/custom:CustomProperty/text()", xmlString);
+    assertXpathEvaluatesTo("true", "/a:entry/custom:CustomProperty/@m:null", xmlString);
+    assertXpathExists("/a:entry/m:properties", xmlString);
+    verifyTagOrdering(xmlString, "category", "Содержание", "CustomProperty", "content", "properties");
+  }
+   
+  @Test
+  public void serializeAtomMediaResourceLinks() throws IOException, XpathException, SAXException, XMLStreamException,
+      FactoryConfigurationError, ODataException {
+    AtomSerializerDeserializer ser = createAtomEntityProvider();
+    employeeData.setWriteProperties(EntitySerializerProperties.serviceRoot(
+        BASE_URI).build());
+    HashMap<String,Object> id = new HashMap<String, Object>();
+    id.put("EmployeeId", "1");
+    employeeData.addNavigation("ne_Manager", id );
+    ODataResponse response =
+        ser.writeEntry(MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees"), employeeData);
+    String xmlString = verifyResponse(response);
+
+    String rel = Edm.NAMESPACE_REL_2007_08 + "ne_Manager";
+
+    assertXpathExists("/a:entry/a:link[@href=\"Managers('1')\"]", xmlString);
+    assertXpathExists("/a:entry/a:link[@rel='" + rel + "']", xmlString);
+    assertXpathExists("/a:entry/a:link[@type='application/atom+xml;type=entry']", xmlString);
+    
+  }
+
+  
+  @Test(expected = EntityProviderException.class)
+  public void navigationLinkWithNullData() throws Exception {
+    Entity roomEntity = new Entity();
+    for (Entry<String, Object> entry : roomData.getProperties().entrySet()) {
+      roomEntity.addProperty(entry.getKey(), entry.getValue());
+    }
+    roomEntity.addNavigation("nr_Building", null);
+    roomEntity.setWriteProperties(EntitySerializerProperties.serviceRoot(BASE_URI)
+        .build());
+    createAtomEntityProvider().writeEntry(
+        MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms"), roomEntity);
+
+  }
+
+  @Test
+  public void navigationLinkWithEmptyData() throws Exception {
+    Entity roomEntity = new Entity();
+    for (Entry<String, Object> entry : roomData.getProperties().entrySet()) {
+      roomEntity.addProperty(entry.getKey(), entry.getValue());
+    }
+    roomEntity.addNavigation("nr_Building", new Entity());
+    roomEntity.setWriteProperties(EntitySerializerProperties.serviceRoot(BASE_URI)
+        .includeMetadata(true).build());
+    final ODataResponse response = createAtomEntityProvider().writeEntry(
+        MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms"), roomEntity);
+
+    final String xmlString = verifyResponse(response);
+    assertXpathExists("/a:entry/a:link[@href=\"Rooms('1')\"]", xmlString);
+    assertXpathNotExists("/a:entry/a:link[@title='nr_Building']", xmlString);
+    assertXpathNotExists("/a:entry/a:link[@href=\"Rooms('1')/nr_Employees\"]", xmlString);
+    assertXpathNotExists("/a:entry/a:link[@href=\"Building('1')\"]", xmlString);
+    assertXpathNotExists("/a:entry/a:link[@type='application/atom+xml;type=feed']", xmlString);
+  }
+
+  @Test
+  public void navigationLinkToOneOfMany() throws Exception {
+    Entity room = new Entity();
+    for (Entry<String, Object> entry : roomData.getProperties().entrySet()) {
+      room.addProperty(entry.getKey(), entry.getValue());
+    }
+    room.addNavigation("nr_Employees", employeeData.getProperties());
+    room.setWriteProperties(
+        EntitySerializerProperties.serviceRoot(BASE_URI)
+            .build());
+    final ODataResponse response = createAtomEntityProvider().writeEntry(
+        MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms"), room);
+    final String xmlString = verifyResponse(response);
+
+    assertXpathExists("/a:entry/a:link[@title='nr_Employees']", xmlString);
+    assertXpathNotExists("/a:entry/a:link[@href=\"Rooms('1')/nr_Employees\"]", xmlString);
+    assertXpathExists("/a:entry/a:link[@href=\"Employees('1')\"]", xmlString);
+    assertXpathExists("/a:entry/a:link[@type='application/atom+xml;type=feed']", xmlString);
+  }
+
+  @Test
+  public void navigationLinkHashMap() throws Exception {
+    Entity roomEntity = new Entity();
+    for (Entry<String, Object> entry : roomData.getProperties().entrySet()) {
+      roomEntity.addProperty(entry.getKey(), entry.getValue());
+    }
+    Map<String, Object> building = new HashMap<String, Object>();
+    building.put("Id", "1");
+    roomEntity.addNavigation("nr_Building", building);
+    roomEntity.setWriteProperties(EntitySerializerProperties.serviceRoot(BASE_URI)
+        .build());
+    final ODataResponse response = createAtomEntityProvider().writeEntry(
+        MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms"), roomEntity);
+
+    final String xmlString = verifyResponse(response);
+
+    assertXpathExists("/a:entry/a:link[@title='nr_Building']", xmlString);
+    assertXpathNotExists("/a:entry/a:link[@href=\"Rooms('1')/nr_Building\"]", xmlString);
+    assertXpathExists("/a:entry/a:link[@href=\"Buildings('1')\"]", xmlString);
+    assertXpathExists("/a:entry/a:link[@type='application/atom+xml;type=entry']", xmlString);
+  }
+
+  @Test
+  public void serializeWithCustomSrcAttributeOnEmployee() throws Exception {
+    AtomSerializerDeserializer ser = createAtomEntityProvider();
+    Entity localEmployeeData = new Entity();
+    for (Entry<String, Object> data : employeeData.getProperties().entrySet()) {
+      localEmployeeData.addProperty(data.getKey(), data.getValue());
+    }
+    String mediaResourceSourceKey = "~src";
+    localEmployeeData.addProperty(mediaResourceSourceKey, "http://localhost:8080/images/image1");
+    EdmEntitySet employeesSet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+    EdmMapping mapping = employeesSet.getEntityType().getMapping();
+    when(mapping.getMediaResourceSourceKey()).thenReturn(mediaResourceSourceKey);
+    localEmployeeData.setWriteProperties(DEFAULT_PROPERTIES);
+    ODataResponse response = ser.writeEntry(employeesSet, localEmployeeData);
+    String xmlString = verifyResponse(response);
+
+    assertXpathExists(
+        "/a:entry/a:link[@href=\"Employees('1')/$value\" and" +
+            " @rel=\"edit-media\" and @type=\"application/octet-stream\"]", xmlString);
+    assertXpathExists("/a:entry/a:content[@type=\"application/octet-stream\"]", xmlString);
+    assertXpathExists("/a:entry/a:content[@src=\"http://localhost:8080/images/image1\"]", xmlString);
+  }
+
+  @Test
+  public void serializeWithCustomSrcAndTypeAttributeOnEmployee() throws Exception {
+    AtomSerializerDeserializer ser = createAtomEntityProvider();
+    Entity localEmployeeData = new Entity();
+    for (Entry<String, Object> data : employeeData.getProperties().entrySet()) {
+      localEmployeeData.addProperty(data.getKey(), data.getValue());
+    }
+    String mediaResourceSourceKey = "~src";
+    localEmployeeData.addProperty(mediaResourceSourceKey, "http://localhost:8080/images/image1");
+    String mediaResourceMimeTypeKey = "~type";
+    localEmployeeData.addProperty(mediaResourceMimeTypeKey, "image/jpeg");
+    EdmEntitySet employeesSet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+    EdmMapping mapping = employeesSet.getEntityType().getMapping();
+    when(mapping.getMediaResourceSourceKey()).thenReturn(mediaResourceSourceKey);
+    when(mapping.getMediaResourceMimeTypeKey()).thenReturn(mediaResourceMimeTypeKey);
+    localEmployeeData.setWriteProperties(DEFAULT_PROPERTIES);
+    ODataResponse response = ser.writeEntry(employeesSet, localEmployeeData);
+    String xmlString = verifyResponse(response);
+
+    assertXpathExists(
+        "/a:entry/a:link[@href=\"Employees('1')/$value\" and" +
+            " @rel=\"edit-media\" and @type=\"image/jpeg\"]", xmlString);
+    assertXpathExists("/a:entry/a:content[@type=\"image/jpeg\"]", xmlString);
+    assertXpathExists("/a:entry/a:content[@src=\"http://localhost:8080/images/image1\"]", xmlString);
+  }
+
+  @Test
+  public void serializeWithCustomSrcAttributeOnRoom() throws Exception {
+    AtomSerializerDeserializer ser = createAtomEntityProvider();
+    Entity localRoomData = new Entity();
+    for (Entry<String, Object> data : roomData.getProperties().entrySet()) {
+      localRoomData.addProperty(data.getKey(), data.getValue());
+    }
+    String mediaResourceSourceKey = "~src";
+    localRoomData.addProperty(mediaResourceSourceKey, "http://localhost:8080/images/image1");
+    EdmEntitySet roomsSet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+    EdmEntityType roomType = roomsSet.getEntityType();
+    EdmMapping mapping = mock(EdmMapping.class);
+    when(roomType.getMapping()).thenReturn(mapping);
+    when(mapping.getMediaResourceSourceKey()).thenReturn(mediaResourceSourceKey);
+    localRoomData.setWriteProperties(DEFAULT_PROPERTIES);
+    ODataResponse response = ser.writeEntry(roomsSet, localRoomData);
+    String xmlString = verifyResponse(response);
+
+    assertXpathNotExists(
+        "/a:entry/a:link[@href=\"Rooms('1')/$value\" and" +
+            " @rel=\"edit-media\" and @type=\"application/octet-stream\"]", xmlString);
+    assertXpathNotExists("/a:entry/a:content[@type=\"application/octet-stream\"]", xmlString);
+    assertXpathNotExists("/a:entry/a:content[@src=\"http://localhost:8080/images/image1\"]", xmlString);
+  }
+
+  @Test
+  public void serializeWithCustomSrcAndTypeAttributeOnRoom() throws Exception {
+    AtomSerializerDeserializer ser = createAtomEntityProvider();
+    Entity localRoomData = new Entity();
+    for (Entry<String, Object> data : roomData.getProperties().entrySet()) {
+      localRoomData.addProperty(data.getKey(), data.getValue());
+    }
+    String mediaResourceSourceKey = "~src";
+    localRoomData.addProperty(mediaResourceSourceKey, "http://localhost:8080/images/image1");
+    String mediaResourceMimeTypeKey = "~type";
+    localRoomData.addProperty(mediaResourceMimeTypeKey, "image/jpeg");
+    EdmEntitySet roomsSet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+    EdmEntityType roomType = roomsSet.getEntityType();
+    EdmMapping mapping = mock(EdmMapping.class);
+    when(roomType.getMapping()).thenReturn(mapping);
+    when(mapping.getMediaResourceSourceKey()).thenReturn(mediaResourceSourceKey);
+    when(mapping.getMediaResourceMimeTypeKey()).thenReturn(mediaResourceMimeTypeKey);
+    localRoomData.setWriteProperties(DEFAULT_PROPERTIES);
+    ODataResponse response = ser.writeEntry(roomsSet, localRoomData);
+    String xmlString = verifyResponse(response);
+
+    assertXpathNotExists(
+        "/a:entry/a:link[@href=\"Rooms('1')/$value\" and" +
+            " @rel=\"edit-media\" and @type=\"image/jpeg\"]", xmlString);
+    assertXpathNotExists("/a:entry/a:content[@type=\"image/jpeg\"]", xmlString);
+    assertXpathNotExists("/a:entry/a:content[@src=\"http://localhost:8080/images/image1\"]", xmlString);
+  }
+
+  private void verifyTagOrdering(final String xmlString, final String... toCheckTags) {
+    XMLUnitHelper.verifyTagOrdering(xmlString, toCheckTags);
+  }
+
+  @Test
+  public void unbalancedPropertyEntryWithInlineEntry() throws Exception {
+
+    Entity roomData = new Entity();
+    roomData.addProperty("Id", "1");
+    roomData.addProperty("Name", "Neu Schwanstein");
+    roomData.addProperty("Seats", new Integer(20));
+    Entity buildingData = new Entity();
+    buildingData.addProperty("Id", "1");
+    buildingData.addProperty("Name", "Building1");
+    roomData.addNavigation("nr_Building", buildingData);
+    EntitySerializerProperties properties =
+        EntitySerializerProperties.serviceRoot(BASE_URI)
+            .includeMetadata(true).build();
+    roomData.setWriteProperties(properties);
+    buildingData.setWriteProperties(properties);
+    AtomSerializerDeserializer provider = createAtomEntityProvider();
+    ODataResponse response =
+        provider.writeEntry(MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms"), roomData);
+
+    String xmlString = verifyResponse(response);
+    assertXpathNotExists("/a:entry/m:properties", xmlString);
+    assertXpathExists("/a:entry/a:link", xmlString);
+    verifyBuilding(buildingXPathString, xmlString);
+  }
+  
+  @Test
+  public void entryWithInlineEntryAndParentProperty() throws Exception {
+
+    Entity roomData = new Entity();
+    roomData.addProperty("Id", "1");
+    roomData.addProperty("Name", "Neu Schwanstein");
+    roomData.addProperty("Seats", new Integer(20));
+    Entity buildingData = new Entity();
+    buildingData.addProperty("Id", "1");
+    buildingData.addProperty("Name", "Building1");
+    roomData.addNavigation("nr_Building", buildingData);
+    EntitySerializerProperties properties =
+        EntitySerializerProperties.serviceRoot(BASE_URI)
+            .includeMetadata(true).build();
+    roomData.setWriteProperties(properties);
+    AtomSerializerDeserializer provider = createAtomEntityProvider();
+    ODataResponse response =
+        provider.writeEntry(MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms"), roomData);
+
+    String xmlString = verifyResponse(response);
+    assertXpathNotExists("/a:entry/m:properties", xmlString);
+    assertXpathExists("/a:entry/a:link", xmlString);
+    verifyBuilding(buildingXPathString, xmlString);
+  }
+  
+  @Test
+  public void entryWithInlineEntryDifferentProperty() throws Exception {
+
+    Entity roomData = new Entity();
+    EntitySerializerProperties properties =
+        EntitySerializerProperties.serviceRoot(BASE_URI)
+            .includeMetadata(true).build();
+    EntitySerializerProperties inline =
+        EntitySerializerProperties.serviceRoot(BASE_URI)
+            .includeMetadata(false).build();
+    roomData.addProperty("Id", "1");
+    roomData.addProperty("Name", "Neu Schwanstein");
+    roomData.addProperty("Seats", new Integer(20));
+    Entity buildingData = new Entity();
+    buildingData.addProperty("Id", "1");
+    buildingData.addProperty("Name", "Building1");
+    buildingData.setWriteProperties(inline);
+    roomData.addNavigation("nr_Building", buildingData);
+    roomData.setWriteProperties(properties);
+    AtomSerializerDeserializer provider = createAtomEntityProvider();
+    ODataResponse response =
+        provider.writeEntry(MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms"), roomData);
+
+    String xmlString = verifyResponse(response);
+    assertXpathNotExists("/a:entry/m:properties", xmlString);
+    assertXpathExists("/a:entry/a:link", xmlString);
+    assertXpathExists(buildingXPathString, xmlString);
+    assertXpathExists(buildingXPathString + "/m:inline", xmlString);
+    assertXpathExists(buildingXPathString + "/m:inline/a:entry[@xml:base='" + BASE_URI + "']", xmlString);
+    assertXpathExists(buildingXPathString + "/m:inline/a:entry", xmlString);
+    assertXpathExists(buildingXPathString + "/m:inline/a:entry/a:content", xmlString);
+    assertXpathExists(buildingXPathString + "/m:inline/a:entry/a:content/m:properties", xmlString);
+    assertXpathExists(buildingXPathString + "/m:inline/a:entry/a:content/m:properties/d:Id", xmlString);
+    assertXpathExists(buildingXPathString + "/m:inline/a:entry/a:content/m:properties/d:Name", xmlString);
+    assertXpathExists("/a:entry/a:content/m:properties/d:Id", xmlString);
+    assertXpathExists("/a:entry/a:content/m:properties/d:Name", xmlString);
+    assertXpathExists("/a:entry/a:content/m:properties/d:Seats", xmlString);
+  }
+
+  
+
+  @Test
+  public void entityWithInlineEntryWithoutId() throws Exception {
+
+    Entity roomData = new Entity();
+    roomData.addProperty("Id", "1");
+    roomData.addProperty("Name", "Neu Schwanstein");
+    roomData.addProperty("Seats", new Integer(20));
+    Entity buildingData = new Entity();
+    buildingData.addProperty("Name", "Building1");
+    roomData.addNavigation("nr_Building", buildingData);
+    EntitySerializerProperties properties =
+        EntitySerializerProperties.serviceRoot(BASE_URI)
+            .build();
+    roomData.setWriteProperties(properties);
+    buildingData.setWriteProperties(properties);
+    AtomSerializerDeserializer provider = createAtomEntityProvider();
+    provider.writeEntry(MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms"), roomData);
+  }
+
+  @Test
+  public void entityWithEmptyInlineEntry() throws Exception {
+
+    Entity roomData = new Entity();
+    roomData.addProperty("Id", "1");
+    roomData.addProperty("Name", "Neu Schwanstein");
+    roomData.addProperty("Seats", new Integer(20));
+    Entity buildingData = new Entity();
+    roomData.addNavigation("nr_Building", buildingData);
+    EntitySerializerProperties properties =
+        EntitySerializerProperties.serviceRoot(BASE_URI)
+            .includeMetadata(true).build();
+    roomData.setWriteProperties(properties);
+    buildingData.setWriteProperties(properties);
+    AtomSerializerDeserializer provider = createAtomEntityProvider();
+    ODataResponse response =
+        provider.writeEntry(MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms"), roomData);
+
+    String xmlString = verifyResponse(response);
+    assertXpathNotExists("/a:entry/m:properties", xmlString);
+    assertXpathExists("/a:entry/a:link", xmlString);
+    assertXpathExists("/a:entry/a:content/m:properties/d:Id", xmlString);
+    assertXpathExists("/a:entry/a:content/m:properties/d:Name", xmlString);
+    assertXpathExists("/a:entry/a:content/m:properties/d:Seats", xmlString);
+  }
+  
+  @Test(expected = EntityProviderException.class)
+  public void entityWithoutIdInlineEntry() throws Exception {
+
+    Entity roomData = new Entity();
+    roomData.addProperty("Name", "Neu Schwanstein");
+    roomData.addProperty("Seats", new Integer(20));
+    Entity buildingData = new Entity();
+    roomData.addNavigation("nr_Building", buildingData);
+    EntitySerializerProperties properties =
+        EntitySerializerProperties.serviceRoot(BASE_URI)
+            .includeMetadata(true).build();
+    roomData.setWriteProperties(properties);
+    buildingData.setWriteProperties(properties);
+    AtomSerializerDeserializer provider = createAtomEntityProvider();
+        provider.writeEntry(MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms"), roomData);
+
+   
+  }
+
+  @Test
+  public void entityWithNullInlineEntry() throws Exception {
+    expectedEx.expect(EntityProviderException.class);
+    expectedEx.expectMessage("Entity or expanded entity cannot have null value.");
+    Entity roomData = new Entity();
+    roomData.addProperty("Id", "1");
+    roomData.addProperty("Name", "Neu Schwanstein");
+    roomData.addProperty("Seats", new Integer(20));
+
+    EntitySerializerProperties properties =
+        EntitySerializerProperties.serviceRoot(BASE_URI)
+            .includeMetadata(true).build();
+    roomData.setWriteProperties(properties);
+    roomData.addNavigation("nr_Building", null);
+    AtomSerializerDeserializer provider = createAtomEntityProvider();
+        provider.writeEntry(MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms"), roomData);
+
+  }
+  
+  private InputStream createStreamReader(final String xml) throws
+  XMLStreamException, UnsupportedEncodingException {
+    return new ByteArrayInputStream(xml.getBytes("UTF-8"));
+  }
+  
+  @Test
+  public void deepInsertEndToEnd() throws Exception {
+    XmlMetadataDeserializer parser = new XmlMetadataDeserializer();
+    String xml = readFile("metadataForDeepInsert.xml");
+    InputStream reader = createStreamReader(xml);
+    EdmDataServices result = parser.readMetadata(reader, true);
+    assertEquals(1, result.getEdm().getSchemas().size());
+    ClientEdm edm = result.getEdm();
+    
+    Entity descMap = new Entity();
+    descMap.addProperty("Product", "CRPROD2");
+    descMap.addProperty("Language", "ES");
+    descMap.addProperty("ProductDescription", "Hola2");
+    EntityCollection descList =  new EntityCollection();
+
+    descList.addEntity(descMap);
+
+    Entity prodCreateFakeMap = new Entity();
+    prodCreateFakeMap.addProperty("Product", "CRPROD2");
+    prodCreateFakeMap.addProperty("ProductType", "HALB");
+    prodCreateFakeMap.addProperty("BaseUnit", "PC");
+
+    prodCreateFakeMap.addNavigation("to_Description", descList);
+   
+    EntitySerializerProperties properties =
+        EntitySerializerProperties.serviceRoot(BASE_URI)
+            .build();
+    prodCreateFakeMap.setWriteProperties(properties);
+    AtomSerializerDeserializer provider = createAtomEntityProvider();
+    ODataResponse response =provider
+        .writeEntry(edm.getDefaultEntityContainer().getEntitySet("A_Product"), prodCreateFakeMap);
+
+    String xmlString = verifyResponse(response);
+    assertXpathNotExists("/a:entry/m:properties", xmlString);
+    assertXpathExists("/a:entry/a:link", xmlString);
+    verifyProduct(productXPathString , xmlString);
+  }
+  
+  protected String readFile(final String filename) throws IOException {
+    InputStream in = getFileAsStream(filename);
+
+    byte[] tmp = new byte[8192];
+    int count = in.read(tmp);
+    StringBuilder b = new StringBuilder();
+    while (count >= 0) {
+      b.append(new String(tmp, 0, count));
+      count = in.read(tmp);
+    }
+
+    return b.toString();
+  }
+  protected InputStream getFileAsStream(final String filename) throws IOException {
+    InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream(filename);
+    if (in == null) {
+      throw new IOException("Requested file '" + filename + "' was not found.");
+    }
+    return in;
+  }
+  @Test
+  public void entityWithInvalidInlineEntryType() throws Exception {
+    expectedEx.expect(EntityProviderException.class);
+    expectedEx.expectMessage("Navigation has to be either an Entity or a Map");
+    Entity roomData = new Entity();
+    roomData.addProperty("Id", "1");
+    roomData.addProperty("Name", "Neu Schwanstein");
+    roomData.addProperty("Seats", new Integer(20));
+
+    EntitySerializerProperties properties =
+        EntitySerializerProperties.serviceRoot(BASE_URI)
+            .includeMetadata(true).build();
+    roomData.setWriteProperties(properties);
+    roomData.addNavigation("nr_Building", new ArrayList<String>());
+    AtomSerializerDeserializer provider = createAtomEntityProvider();
+        provider.writeEntry(MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms"), roomData);
+
+  }
+
+  private void verifyBuilding(final String path, final String xmlString) throws XpathException, IOException,
+      SAXException {
+    assertXpathExists(path, xmlString);
+    assertXpathExists(path + "/m:inline", xmlString);
+
+    assertXpathExists(path + "/m:inline/a:entry[@xml:base='" + BASE_URI + "']", xmlString);
+    assertXpathExists(path + "/m:inline/a:entry", xmlString);
+    assertXpathExists(path + "/m:inline/a:entry/a:id", xmlString);
+    assertXpathExists(path + "/m:inline/a:entry/a:title", xmlString);
+    assertXpathExists(path + "/m:inline/a:entry/a:updated", xmlString);
+
+    assertXpathExists(path + "/m:inline/a:entry/a:category", xmlString);
+    assertXpathExists(path + "/m:inline/a:entry/a:link", xmlString);
+
+    assertXpathExists(path + "/m:inline/a:entry/a:content", xmlString);
+    assertXpathExists(path + "/m:inline/a:entry/a:content/m:properties", xmlString);
+    assertXpathExists(path + "/m:inline/a:entry/a:content/m:properties/d:Id", xmlString);
+    assertXpathExists(path + "/m:inline/a:entry/a:content/m:properties/d:Name", xmlString);
+
+    assertXpathExists("/a:entry/a:content/m:properties/d:Id", xmlString);
+    assertXpathExists("/a:entry/a:content/m:properties/d:Name", xmlString);
+    assertXpathExists("/a:entry/a:content/m:properties/d:Seats", xmlString);
+
+  }
+  
+
+  private void verifyProduct(final String path, final String xmlString) throws XpathException, IOException,
+      SAXException {
+    assertXpathExists(path, xmlString);
+    assertXpathExists(path + "/m:inline", xmlString);
+
+    assertXpathExists(path + "/m:inline/a:feed[@xml:base='" + BASE_URI + "']", xmlString);
+    assertXpathExists(path + "/m:inline/a:feed", xmlString);
+    assertXpathExists(path + "/m:inline/a:feed/a:id", xmlString);
+    assertXpathExists(path + "/m:inline/a:feed/a:title", xmlString);
+    assertXpathExists(path + "/m:inline/a:feed/a:updated", xmlString);
+
+    assertXpathExists(path + "/m:inline/a:feed/a:author", xmlString);
+    assertXpathExists(path + "/m:inline/a:feed/a:link", xmlString);
+    ;
+    assertXpathExists("/a:entry/a:link/m:inline/a:feed/a:entry", xmlString);
+    assertXpathExists("/a:entry/a:link/m:inline/a:feed/a:entry/a:content/m:properties/d:Product", xmlString);
+    assertXpathExists("/a:entry/a:link/m:inline/a:feed/a:entry/a:content/m:properties/d:Language", xmlString);
+    assertXpathExists("/a:entry/a:link/m:inline/a:feed/a:entry/a:content/m:properties/d:ProductDescription", xmlString);
+    
+    assertXpathExists("/a:entry/a:content/m:properties/d:Product", xmlString);
+    assertXpathExists("/a:entry/a:content/m:properties/d:BaseUnit", xmlString);
+    assertXpathExists("/a:entry/a:content/m:properties/d:ProductType", xmlString);
+  }
+  
+  @Test
+  public void entityWithInlineEntryWithoutKeys() throws Exception {
+
+    Entity roomData = new Entity();
+    roomData.addProperty("Name", "Neu Schwanstein");
+    roomData.addProperty("Seats", new Integer(20));
+    Entity buildingData = new Entity();
+    buildingData.addProperty("Name", "Building1");
+    roomData.addNavigation("nr_Building", buildingData);
+    EntitySerializerProperties properties =
+        EntitySerializerProperties.serviceRoot(BASE_URI).isKeyAutoGenerated(true)
+            .build();
+    roomData.setWriteProperties(properties);
+    buildingData.setWriteProperties(properties);
+    AtomSerializerDeserializer provider = createAtomEntityProvider();
+    ODataResponse response = provider.writeEntry(MockFacade.getMockEdm().
+        getDefaultEntityContainer().getEntitySet("Rooms"), roomData);
+    String xmlString = verifyResponse(response);
+    assertXpathExists("/a:entry/a:link[@href=\"Rooms('A')/nr_Building\"]", xmlString);
+    assertXpathExists("/a:entry/a:link[@href=\"Rooms('A')/nr_Building\"]/m:inline", xmlString);
+    assertXpathExists("/a:entry/a:link[@href=\"Rooms('A')/nr_Building\"]/m:inline/a:entry/"
+        + "a:content/m:properties", xmlString);
+    assertXpathExists("/a:entry/a:link[@href=\"Rooms('A')/nr_Building\"]/m:inline/a:entry/"
+        + "a:content/m:properties/d:Name", xmlString);
+    assertXpathExists("/a:entry/a:content/m:properties/d:Seats", xmlString);
+    assertXpathExists("/a:entry/a:content/m:properties/d:Name", xmlString);
+  }
+  
+  @Test
+  public void entityWithInlineEntryWithoutKeysWithMetadata() throws Exception {
+
+    Entity roomData = new Entity();
+    roomData.addProperty("Name", "Neu Schwanstein");
+    roomData.addProperty("Seats", new Integer(20));
+    Entity buildingData = new Entity();
+    buildingData.addProperty("Name", "Building1");
+    roomData.addNavigation("nr_Building", buildingData);
+    EntitySerializerProperties properties =
+        EntitySerializerProperties.serviceRoot(BASE_URI).isKeyAutoGenerated(true).includeMetadata(true)
+            .build();
+    roomData.setWriteProperties(properties);
+    buildingData.setWriteProperties(properties);
+    AtomSerializerDeserializer provider = createAtomEntityProvider();
+    ODataResponse response = provider.writeEntry(MockFacade.getMockEdm().
+        getDefaultEntityContainer().getEntitySet("Rooms"), roomData);
+    String xmlString = verifyResponse(response);
+    assertXpathExists("/a:entry/a:id", xmlString);
+    assertXpathExists("/a:entry/a:link[@href=\"Rooms('A')/nr_Building\"]", xmlString);
+    assertXpathExists("/a:entry/a:link[@href=\"Rooms('A')/nr_Building\"]/m:inline", xmlString);
+    assertXpathExists("/a:entry/a:link[@href=\"Rooms('A')/nr_Building\"]/m:inline/a:entry/"
+        + "a:content/m:properties", xmlString);
+    assertXpathExists("/a:entry/a:link[@href=\"Rooms('A')/nr_Building\"]/m:inline/a:entry/"
+        + "a:id", xmlString);
+    assertXpathExists("/a:entry/a:link[@href=\"Rooms('A')/nr_Building\"]/m:inline/a:entry/"
+        + "a:content/m:properties/d:Name", xmlString);
+    assertXpathExists("/a:entry/a:content/m:properties/d:Seats", xmlString);
+    assertXpathExists("/a:entry/a:content/m:properties/d:Name", xmlString);
+  }
+  
+  @Test
+  public void navigationLinkToOneOfManyWithoutKeys() throws Exception {
+    Entity roomData = new Entity();
+    roomData.addProperty("Name", "Neu Schwanstein");
+    roomData.addProperty("Seats", new Integer(20));
+    roomData.addProperty("Version", new Integer(3));
+    
+    employeeData = new Entity();
+
+    Calendar date = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
+    date.clear();
+    date.set(1999, 0, 1);
+    
+    Entity employeeData = new Entity();
+    employeeData.addProperty("ImmageUrl", null);
+    employeeData.addProperty("ManagerId", "1");
+    employeeData.addProperty("Age", new Integer(52));
+    employeeData.addProperty("RoomId", "1");
+    employeeData.addProperty("EntryDate", date);
+    employeeData.addProperty("TeamId", "42");
+    employeeData.addProperty("EmployeeName", "Walter Winter");
+    
+    roomData.addNavigation("nr_Employees", employeeData.getProperties());
+    roomData.setWriteProperties(
+        EntitySerializerProperties.serviceRoot(BASE_URI).isKeyAutoGenerated(true)
+            .build());
+    final ODataResponse response = createAtomEntityProvider().writeEntry(
+        MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms"), roomData);
+    final String xmlString = verifyResponse(response);
+
+    assertXpathExists("/a:entry/a:link[@title='nr_Employees']", xmlString);
+    assertXpathNotExists("/a:entry/a:link[@href=\"Rooms('1')/nr_Employees\"]", xmlString);
+    assertXpathExists("/a:entry/a:link[@href=\"Employees('A')\"]", xmlString);
+    assertXpathExists("/a:entry/a:link[@type='application/atom+xml;type=feed']", xmlString);
+  }
+  
+  @Test
+  public void contentOnlyWithoutKeyWithoutSelectedProperties() throws Exception {
+    Entity employeeData = new Entity();
+    employeeData.addProperty("ManagerId", "1");
+    employeeData.addProperty("Age", new Integer(52));
+    employeeData.addProperty("RoomId", "1");
+    employeeData.addProperty("TeamId", "42");
+
+    employeeData.setWriteProperties(
+        EntitySerializerProperties.serviceRoot(BASE_URI).build());
+    
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+
+    try {
+      createAtomEntityProvider().writeEntry(entitySet, employeeData);
+    } catch (EntityProviderProducerException e) {
+      assertTrue(e.getMessage().contains("The metadata do not allow a null value for property 'EmployeeId'"));
+    }
+  }
+  
+  @Test
+  public void testWithoutCompositeKey() throws Exception {
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getEntityContainer("Container2").getEntitySet("Photos");
+    
+    Entity photoData = new Entity();
+    photoData.addProperty("Name", "Mona Lisa");
+    photoData.setWriteProperties(
+        EntitySerializerProperties.serviceRoot(BASE_URI).build());
+
+    try {
+      createAtomEntityProvider().writeEntry(entitySet, photoData);
+    } catch (EntityProviderProducerException e) {
+      assertTrue(e.getMessage().contains("The metadata do not allow a null value for property 'Id'"));
+    }
+  }
+  
+  @Test
+  public void testWithoutCompositeKeyWithOneKeyNull() throws Exception {
+    Edm edm = MockFacade.getMockEdm();
+    EdmEntitySet entitySet = edm.getEntityContainer("Container2").getEntitySet("Photos");
+    
+    Entity photoData = new Entity();
+    photoData.addProperty("Name", "Mona Lisa");
+    photoData.addProperty("Id", Integer.valueOf(1));
+    photoData.setWriteProperties(
+        EntitySerializerProperties.serviceRoot(BASE_URI).build());
+    
+    EdmTyped typeProperty = edm.getEntityContainer("Container2").getEntitySet("Photos").
+        getEntityType().getProperty("Type");
+    EdmFacets facets = mock(EdmFacets.class);
+    when(facets.getConcurrencyMode()).thenReturn(EdmConcurrencyMode.Fixed);
+    when(facets.getMaxLength()).thenReturn(3);
+    when(((EdmProperty) typeProperty).getFacets()).thenReturn(facets);
+
+    try {
+      createAtomEntityProvider().writeEntry(entitySet, photoData);
+    } catch (EntityProviderProducerException e) {
+      assertTrue(e.getMessage().contains("The metadata do not allow a null value for property 'Type'"));
+    }
+  }
+  
+  @Test
+  public void testExceptionWithNonNullablePropertyIsNull() throws Exception {
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Organizations");
+    EdmProperty nameProperty = (EdmProperty) entitySet.getEntityType().getProperty("Name");
+    EdmFacets facets = nameProperty.getFacets();
+    when(facets.isNullable()).thenReturn(new Boolean(false));
+    
+    Entity orgData = new Entity();
+    orgData.addProperty("Id", "1");
+    orgData.setWriteProperties(EntitySerializerProperties.serviceRoot(BASE_URI).build());
+    try {
+      createAtomEntityProvider().writeEntry(entitySet, orgData);
+    } catch (EntityProviderProducerException e) {
+      assertTrue(e.getMessage().contains("The metadata do not allow a null value for property 'Name'"));
+    }
+  }
+  
+  @Test
+  public void testExceptionWithNonNullablePropertyIsNull1() throws Exception {
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Organizations");
+    EdmProperty kindProperty = (EdmProperty) entitySet.getEntityType().getProperty("Kind");
+    EdmFacets facets = kindProperty.getFacets();
+    when(facets.isNullable()).thenReturn(new Boolean(false));
+    
+    EdmProperty nameProperty = (EdmProperty) entitySet.getEntityType().getProperty("Name");
+    when(nameProperty.getFacets()).thenReturn(null);
+    
+    Entity orgData = new Entity();
+    orgData.addProperty("Id", "1");
+    orgData.addProperty("Name", "Org1");
+    orgData.setWriteProperties(EntitySerializerProperties.serviceRoot(BASE_URI).build());
+    try {
+      createAtomEntityProvider().writeEntry(entitySet, orgData);
+    } catch (EntityProviderProducerException e) {
+   

<TRUNCATED>

[06/24] olingo-odata2 git commit: [OLINGO-1253]Client Module for Olingo v2

Posted by ar...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/uri/EdmUriBuilderTest.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/uri/EdmUriBuilderTest.java b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/uri/EdmUriBuilderTest.java
new file mode 100644
index 0000000..4e4baf6
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/uri/EdmUriBuilderTest.java
@@ -0,0 +1,988 @@
+package org.apache.olingo.odata2.client.core.uri;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.net.URI;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmComplexType;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmFunctionImport;
+import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
+import org.apache.olingo.odata2.api.edm.EdmParameter;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.client.api.uri.QueryOption;
+import org.apache.olingo.odata2.testutil.mock.MockFacade;
+import org.junit.Before;
+import org.junit.Test;
+
+public class EdmUriBuilderTest {
+  
+  protected static final String SERVICE_ROOT_URI = "http://host:80/service/";
+  protected static final String SERVICE_ROOT_URI_1 = "http://host:80/service";
+  private Edm edm;
+
+  @Before
+  public void getEdm() throws ODataException {
+    edm = MockFacade.getMockEdm();
+  }
+  
+  @Test
+  public void testUriSimpleES() throws EdmException {
+    URI uri = new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment(edm.getDefaultEntityContainer().getEntitySet("Employees")).
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Employees", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testSimpleESWithCountUri1() throws EdmException {
+    URI uri = new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment(edm.getDefaultEntityContainer().getEntitySet("Employees")).
+    appendCountSegment().
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Employees/$count", uri.toASCIIString());
+  }
+  
+  @Test(expected=RuntimeException.class)
+  public void negTestWithCountAndFormat() throws EdmException {
+    new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment(edm.getDefaultEntityContainer().getEntitySet("Employees")).
+    appendCountSegment().
+    format("application/json").
+    build();
+  }
+  
+  @Test
+  public void testSimpleESWithCountUri2() throws EdmException {
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Managers");
+    URI uri = new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment(entitySet).
+    appendKeySegment((EdmProperty)entitySet.getEntityType().getProperty("EmployeeId"), "1").
+    appendNavigationSegment((EdmNavigationProperty)entitySet.getEntityType().getProperty("nm_Employees")).
+    appendCountSegment().
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Managers('1')/nm_Employees/$count", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testSimpleESWithCountAndFilter() throws EdmException {
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Managers");
+    URI uri = new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment(entitySet).
+    appendKeySegment((EdmProperty)entitySet.getEntityType().getProperty("EmployeeId"), "1").
+    appendNavigationSegment((EdmNavigationProperty)entitySet.getEntityType().getProperty("nm_Employees")).
+    appendCountSegment().
+    addQueryOption(QueryOption.FILTER, "TeamId eq '1'").
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Managers('1')/nm_Employees/"
+        + "$count?$filter=TeamId%20eq%20'1'", uri.toASCIIString());
+  }
+  
+  @Test(expected=RuntimeException.class)
+  public void negTestUriWithCountSegment1() throws EdmException {
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Managers");
+    EdmEntitySet employeeEntitySet = edm.getDefaultEntityContainer().getEntitySet("Employees");
+    new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment(entitySet).
+    appendKeySegment((EdmProperty)entitySet.getEntityType().getProperty("EmployeeId"), "1").
+    appendNavigationSegment((EdmNavigationProperty)entitySet.getEntityType().getProperty("nm_Employees")).
+    appendKeySegment((EdmProperty)employeeEntitySet.getEntityType().getProperty("EmployeeId"), "1").
+    appendCountSegment().
+    build();
+  }
+  
+  @Test(expected=RuntimeException.class)
+  public void negTestUriWithCountSegment2() throws EdmException {
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Managers");
+    EdmEntitySet employeeEntitySet = edm.getDefaultEntityContainer().getEntitySet("Employees");
+    new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment(entitySet).
+    appendKeySegment((EdmProperty)entitySet.getEntityType().getProperty("EmployeeId"), "1").
+    appendNavigationSegment((EdmNavigationProperty)entitySet.getEntityType().getProperty("nm_Employees")).
+    appendKeySegment((EdmProperty)employeeEntitySet.getEntityType().getProperty("EmployeeId"), "1").
+    appendNavigationSegment((EdmNavigationProperty)employeeEntitySet.getEntityType().getProperty("ne_Team")).
+    appendCountSegment().
+    build();
+  }
+  
+  @Test
+  public void testMetadataUri() throws EdmException {
+    URI uri = new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+    appendMetadataSegment().
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/$metadata", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testSimpleESWithKeyUri() throws EdmException {
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Employees");
+    URI uri = new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment(entitySet).
+    appendKeySegment((EdmProperty) entitySet.getEntityType().getProperty("EmployeeId"), "1").
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Employees('1')", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testCompositeKeysUri() throws EdmException {
+    EdmEntitySet entitySet = edm.getEntityContainer("Container2").getEntitySet("Photos");
+    Map<EdmProperty, Object> keyMap = new LinkedHashMap<EdmProperty,Object>();
+    keyMap.put((EdmProperty) entitySet.getEntityType().getProperty("Id"), 4);
+    keyMap.put((EdmProperty) entitySet.getEntityType().getProperty("Type"), "foo");
+    URI uri = new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment(entitySet).
+    appendKeySegment(keyMap).
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Photos(Id=4,Type='foo')", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testFilterUri() throws EdmException {
+    EdmEntitySet entitySet = edm.getEntityContainer("Container2").getEntitySet("Photos");
+    URI uri = new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment(entitySet).
+    filter("Name eq 'Photo 1'").
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Photos?$filter=Name%20eq%20'Photo%201'", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testTopUri1() throws EdmException {
+    EdmEntitySet entitySet = edm.getEntityContainer("Container2").getEntitySet("Photos");
+    URI uri = new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment(entitySet).
+    top(2).
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Photos?$top=2", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testTopUri2() throws EdmException {
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Managers");
+    URI uri = new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment(entitySet).
+    appendKeySegment((EdmProperty)entitySet.getEntityType().getProperty("EmployeeId"), "1").
+    appendNavigationSegment((EdmNavigationProperty)entitySet.getEntityType().getProperty("nm_Employees")).
+    addQueryOption(QueryOption.FILTER, "TeamId eq '1'").
+    top(2).
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Managers('1')/nm_Employees"
+        + "?$filter=TeamId%20eq%20'1'&$top=2", uri.toASCIIString());
+  }
+  
+  @Test(expected=RuntimeException.class)
+  public void negTestQueryOption() throws EdmException {
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Managers");
+    EdmEntitySet employeeEntitySet = edm.getDefaultEntityContainer().getEntitySet("Employees");
+    URI uri = new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment(entitySet).
+    appendKeySegment((EdmProperty)entitySet.getEntityType().getProperty("EmployeeId"), "1").
+    appendNavigationSegment((EdmNavigationProperty)entitySet.getEntityType().getProperty("nm_Employees")).
+    appendKeySegment((EdmProperty)employeeEntitySet.getEntityType().getProperty("EmployeeId"), "1").
+    addQueryOption(QueryOption.FILTER, "TeamId eq '1'").
+    top(2).
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Managers('1')/nm_Employees"
+        + "?$filter=TeamId%20eq%20'1'&$top=2", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testSkipUri() throws EdmException {
+    EdmEntitySet entitySet = edm.getEntityContainer("Container2").getEntitySet("Photos");
+    URI uri = new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment(entitySet).
+    skip(2).
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Photos?$skip=2", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testUriWithQueryOptions() throws EdmException {
+    EdmEntitySet entitySet = edm.getEntityContainer("Container2").getEntitySet("Photos");
+    URI uri = new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment(entitySet).
+    filter("Name eq 'Photo 1'").
+    top(2).
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Photos?$filter=Name%20eq%20'Photo%201'&$top=2", uri.toASCIIString());
+  }
+   
+  @Test
+  public void testUriWithNavigationSegment1() throws EdmException {
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Employees");
+    URI uri = new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment(entitySet).
+    appendKeySegment((EdmProperty)entitySet.getEntityType().getProperty("EmployeeId"), "1").
+    appendNavigationSegment((EdmNavigationProperty)entitySet.getEntityType().getProperty("ne_Team")).
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Employees('1')/ne_Team", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testUriWithNavigationSegment2() throws EdmException {
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Managers");
+    EdmEntitySet employeeEntitySet = edm.getDefaultEntityContainer().getEntitySet("Employees");
+    URI uri = new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment(entitySet).
+    appendKeySegment((EdmProperty)entitySet.getEntityType().getProperty("EmployeeId"), "1").
+    appendNavigationSegment((EdmNavigationProperty)entitySet.getEntityType().getProperty("nm_Employees")).
+    appendKeySegment((EdmProperty)employeeEntitySet.getEntityType().getProperty("EmployeeId"), "1").
+    appendNavigationSegment((EdmNavigationProperty)employeeEntitySet.getEntityType().getProperty("ne_Team")).
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Managers('1')/nm_Employees('1')/ne_Team", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testUriWithNavigationSegment3() throws EdmException {
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Employees");
+    EdmEntitySet teamEntitySet = edm.getDefaultEntityContainer().getEntitySet("Teams");
+    URI uri = new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment(entitySet).
+    appendKeySegment((EdmProperty)entitySet.getEntityType().getProperty("EmployeeId"), "1").
+    appendNavigationSegment((EdmNavigationProperty)entitySet.getEntityType().getProperty("ne_Team")).
+    appendNavigationSegment((EdmNavigationProperty)teamEntitySet.getEntityType().getProperty("nt_Employees")).
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Employees('1')/ne_Team/nt_Employees", uri.toASCIIString());
+  }
+  
+  @Test(expected=RuntimeException.class)
+  public void negTest1UriWithNavigationSegment() throws EdmException {
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Managers");
+    EdmEntitySet employeeEntitySet = edm.getDefaultEntityContainer().getEntitySet("Employees");
+    new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment(entitySet).
+    appendKeySegment((EdmProperty)entitySet.getEntityType().getProperty("EmployeeId"), "1").
+    appendNavigationSegment((EdmNavigationProperty)entitySet.getEntityType().getProperty("nm_Employees")).
+    appendNavigationSegment((EdmNavigationProperty)employeeEntitySet.getEntityType().getProperty("ne_Team")).
+    build();
+  }
+  
+  @Test(expected=RuntimeException.class)
+  public void negTest2UriWithNavigationSegment() throws EdmException {
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Employees");
+    new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment(entitySet).
+    appendNavigationSegment((EdmNavigationProperty)entitySet.getEntityType().getProperty("ne_Team")).
+    build();
+  }
+  
+  @Test
+  public void testUriWithSimplePropertySegment() throws EdmException {
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Employees");
+    URI uri = new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment(entitySet).
+    appendKeySegment((EdmProperty)entitySet.getEntityType().getProperty("EmployeeId"), "1").
+    appendPropertySegment((EdmProperty)entitySet.getEntityType().getProperty("EmployeeName"), "EmployeeName").
+    appendValueSegment().
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Employees('1')/EmployeeName/$value", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testUriWithComplexPropertySegment() throws EdmException {
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Employees");
+    URI uri = new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment(entitySet).
+    appendKeySegment((EdmProperty)entitySet.getEntityType().getProperty("EmployeeId"), "1").
+    appendPropertySegment((EdmProperty)entitySet.getEntityType().getProperty("Location"), "Location").
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Employees('1')/Location", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testUriWithComplexPropertySegment1() throws EdmException {
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Employees");
+    EdmComplexType complexType = edm.getComplexType("RefScenario", "c_Location");
+    EdmProperty property = (EdmProperty) complexType.getProperty("City");
+    URI uri = new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment(entitySet).
+    appendKeySegment((EdmProperty)entitySet.getEntityType().getProperty("EmployeeId"), "1").
+    appendPropertySegment((EdmProperty)entitySet.getEntityType().getProperty("Location"), "Location").
+    appendPropertySegment(property, "City").
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Employees('1')/Location/City", uri.toASCIIString());
+  }
+  
+  @Test(expected = RuntimeException.class)
+  public void testUriWithComplexPropertySegmentWithValueSegment() throws EdmException {
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Employees");
+    EdmComplexType complexType = edm.getComplexType("RefScenario", "c_Location");
+    EdmProperty property = (EdmProperty) complexType.getProperty("City");
+    new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment(entitySet).
+    appendKeySegment((EdmProperty)entitySet.getEntityType().getProperty("EmployeeId"), "1").
+    appendPropertySegment((EdmProperty)entitySet.getEntityType().getProperty("Location"), "Location").
+    appendPropertySegment(property, "City").
+    appendValueSegment().
+    build();
+  }
+  
+  @Test(expected = RuntimeException.class)
+  public void negTestUriWithFormat() throws EdmException {
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Employees");
+    EdmComplexType complexType = edm.getComplexType("RefScenario", "c_Location");
+    EdmProperty property = (EdmProperty) complexType.getProperty("City");
+    EdmComplexType complexType1 = (EdmComplexType) property.getType();
+    EdmProperty property1 = (EdmProperty) complexType1.getProperty("CityName");
+    new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment(entitySet).
+    appendKeySegment((EdmProperty)entitySet.getEntityType().getProperty("EmployeeId"), "1").
+    appendPropertySegment((EdmProperty)entitySet.getEntityType().getProperty("Location"), "Location").
+    appendPropertySegment(property, "City").
+    appendPropertySegment(property1, "CityName").
+    appendValueSegment().
+    format("application/json").
+    build();
+  }
+  
+  @Test(expected=RuntimeException.class)
+  public void wrongESInUri() throws EdmException {
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Employee");
+    new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment(entitySet).
+    build();
+  }
+  
+  @Test(expected = RuntimeException.class)
+  public void duplicateKeyPropertyInUri() throws EdmException {
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Employees");
+    new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment(entitySet).
+    appendKeySegment((EdmProperty)entitySet.getEntityType().getProperty("EmployeeId"), "1").
+    appendKeySegment((EdmProperty)entitySet.getEntityType().getProperty("EmployeeId"), "1").
+    build();
+  }
+  
+  @Test(expected=RuntimeException.class)
+  public void duplicateKeyForNavPropertyInUri() throws EdmException {
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Managers");
+    EdmEntitySet empEntitySet = edm.getDefaultEntityContainer().getEntitySet("Employees");
+    new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment(entitySet).
+    appendKeySegment((EdmProperty)entitySet.getEntityType().getProperty("EmployeeId"), "1").
+    appendNavigationSegment((EdmNavigationProperty)entitySet.getEntityType().getProperty("nm_Employees")).
+    appendKeySegment((EdmProperty)empEntitySet.getEntityType().getProperty("EmployeeId"), "1").
+    appendKeySegment((EdmProperty)empEntitySet.getEntityType().getProperty("EmployeeId"), "1").
+    build();
+  }
+  
+  @Test
+  public void testNavigationToManyInUri() throws EdmException {
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Managers");
+    EdmEntitySet empEntitySet = edm.getDefaultEntityContainer().getEntitySet("Employees");
+    Map<EdmProperty, Object> keyMap = new HashMap<EdmProperty, Object>();
+    keyMap.put((EdmProperty)empEntitySet.getEntityType().getProperty("EmployeeId"), "1");
+    URI uri = new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment(entitySet).
+    appendKeySegment((EdmProperty)entitySet.getEntityType().getProperty("EmployeeId"), "1").
+    appendNavigationSegment((EdmNavigationProperty)entitySet.getEntityType().getProperty("nm_Employees")).
+    appendKeySegment(keyMap).
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Managers('1')/nm_Employees(EmployeeId='1')", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testUriWithOrderby() throws EdmException {
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Managers");
+    URI uri = new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment(entitySet).
+    appendKeySegment((EdmProperty)entitySet.getEntityType().getProperty("EmployeeId"), "1").
+    appendNavigationSegment((EdmNavigationProperty)entitySet.getEntityType().getProperty("nm_Employees")).
+    orderBy("EmployeeId").
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Managers('1')/nm_Employees?$orderby=EmployeeId", uri.toASCIIString());
+  }
+  
+  @Test(expected=RuntimeException.class)
+  public void negTestUriWithOrderby() throws EdmException {
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Managers");
+    new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment(entitySet).
+    appendKeySegment((EdmProperty)entitySet.getEntityType().getProperty("EmployeeId"), "1").
+    orderBy("EmployeeId").
+    build();
+  }
+  
+  @Test
+  public void testUriWithOrderbyAndFormat() throws EdmException {
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Managers");
+    URI uri = new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment(entitySet).
+    appendKeySegment((EdmProperty)entitySet.getEntityType().getProperty("EmployeeId"), "1").
+    appendNavigationSegment((EdmNavigationProperty)entitySet.getEntityType().getProperty("nm_Employees")).
+    orderBy("EmployeeId").
+    format("application/json").
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Managers('1')/nm_Employees"
+        + "?$orderby=EmployeeId&$format=application%2Fjson", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testUriWithOrderbyWithNullValue() throws EdmException {
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Managers");
+    try {
+      new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+      appendEntitySetSegment(entitySet).
+      appendKeySegment((EdmProperty)entitySet.getEntityType().getProperty("EmployeeId"), "1").
+      appendNavigationSegment((EdmNavigationProperty)entitySet.getEntityType().getProperty("nm_Employees")).
+      orderBy("EmployeeName").
+      build();
+    } catch(EdmException e) {
+      assertEquals("Property not defined.", e.getMessage());
+    }
+  }
+  
+  @Test
+  public void testUriWithSelect() throws EdmException {
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Managers");
+    URI uri = new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment(entitySet).
+    appendKeySegment((EdmProperty)entitySet.getEntityType().getProperty("EmployeeId"), "1").
+    appendNavigationSegment((EdmNavigationProperty)entitySet.getEntityType().getProperty("nm_Employees")).
+    select("EmployeeId", "EmployeeName", "RoomId", "TeamId").
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Managers('1')/nm_Employees"
+        + "?$select=EmployeeId%2CEmployeeName%2CRoomId%2CTeamId", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testUriWithSelectAndFilter() throws EdmException {
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Managers");
+    URI uri = new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment(entitySet).
+    appendKeySegment((EdmProperty)entitySet.getEntityType().getProperty("EmployeeId"), "1").
+    appendNavigationSegment((EdmNavigationProperty)entitySet.getEntityType().getProperty("nm_Employees")).
+    filter("EmployeeId eq 1").
+    select("EmployeeId", "EmployeeName", "RoomId", "TeamId").
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Managers('1')/nm_Employees?$filter="
+        + "EmployeeId%20eq%201&$select=EmployeeId%2CEmployeeName%2CRoomId%2CTeamId", uri.toASCIIString());
+  }
+  
+  @Test(expected=RuntimeException.class)
+  public void testUriWithSelectAndCount() throws EdmException {
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Managers");
+    new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment(entitySet).
+    appendKeySegment((EdmProperty)entitySet.getEntityType().getProperty("EmployeeId"), "1").
+    appendNavigationSegment((EdmNavigationProperty)entitySet.getEntityType().getProperty("nm_Employees")).
+    appendCountSegment().
+    select("EmployeeId", "EmployeeName", "RoomId", "TeamId").
+    build();
+  }
+  
+  @Test
+  public void testUriWithSelectOnEntity() throws EdmException {
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Managers");
+    URI uri = new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment(entitySet).
+    appendKeySegment((EdmProperty)entitySet.getEntityType().getProperty("EmployeeId"), "1").
+    select("EmployeeId", "EmployeeName", "RoomId", "TeamId").
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Managers('1')"
+        + "?$select=EmployeeId%2CEmployeeName%2CRoomId%2CTeamId", uri.toASCIIString());
+  }
+  
+  @Test(expected=RuntimeException.class)
+  public void testUriWithSelectOnEntityWithTop() throws EdmException {
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Managers");
+    new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment(entitySet).
+    appendKeySegment((EdmProperty)entitySet.getEntityType().getProperty("EmployeeId"), "1").
+    select("EmployeeId", "EmployeeName", "RoomId", "TeamId").
+    top(2).
+    build();
+  }
+  
+  @Test
+  public void testUriWithExpand() throws EdmException {
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Managers");
+    URI uri = new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment(entitySet).
+    appendKeySegment((EdmProperty)entitySet.getEntityType().getProperty("EmployeeId"), "1").
+    expand("nm_Employees").
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Managers('1')?$expand=nm_Employees", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testUriWithExpandAndFilter() throws EdmException {
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Managers");
+    URI uri = new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment(entitySet).
+    expand("nm_Employees").
+    filter("EmployeeName eq 'Walter Winter'").
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Managers?$expand=nm_Employees&$filter="
+        + "EmployeeName%20eq%20'Walter%20Winter'", uri.toASCIIString());
+  }
+  
+  @Test(expected=RuntimeException.class)
+  public void testUriWithExpandAndCount() throws EdmException {
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Managers");
+    new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment(entitySet).
+    appendCountSegment().
+    expand("nm_Employees").
+    build();
+  }
+  
+  @Test
+  public void testUriWithFilterAndExpand() throws EdmException {
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Managers");
+    URI uri = new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment(entitySet).
+    filter("EmployeeName eq 'Walter Winter'").
+    expand("nm_Employees").
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Managers?$filter=EmployeeName%20eq%20'Walter%20Winter'"
+        + "&$expand=nm_Employees", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testUriWithCustomQueryOption() throws EdmException {
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Employees");
+    URI uri = new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment(entitySet).
+    top(2).
+    addCustomQueryOption("x", "y").
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Employees?$top=2&x=y", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testUriWithCustomQueryOptionWithFormat() throws EdmException {
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Employees");
+    URI uri = new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment(entitySet).
+    top(2).
+    addCustomQueryOption("x", "y").
+    format("application/json").
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Employees?$top=2&$format=application%2Fjson&x=y", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testUriWithFilters() throws EdmException {
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Managers");
+    URI uri = new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment(entitySet).
+    filter("EmployeeId ge '1' and EmployeeId le '10'").
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Managers?$filter=EmployeeId%20ge%20'1'%20"
+        + "and%20EmployeeId%20le%20'10'", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testUriWithDuplicateExpands() throws EdmException {
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Managers");
+    URI uri = new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment(entitySet).
+    expand("nm_Employees").
+    expand("nm_Employees").
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Managers?$expand=nm_Employees%2Cnm_Employees", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testUriWithTwoCustomQueryOptions() throws EdmException {
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Employees");
+    URI uri = new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment(entitySet).
+    top(2).
+    addCustomQueryOption("x", "y").
+    addCustomQueryOption("z", "y").
+    format("application/json").
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Employees?$top=2&$"
+        + "format=application%2Fjson&x=y&z=y", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testUriWithOnlyCustomQueryOption() throws EdmException {
+    URI uri = new EdmURIBuilderImpl(SERVICE_ROOT_URI_1).
+    addCustomQueryOption("x", "y").
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service?x=y", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testUriWithDuplicateOrderby() throws EdmException {
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Managers");
+    URI uri = new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment(entitySet).
+    orderBy("EmployeeId").
+    orderBy("EmployeeId").
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Managers?$orderby=EmployeeId%2CEmployeeId", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testUriWithTwoOrderby() throws EdmException {
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Employees");
+    URI uri = new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment(entitySet).
+    orderBy("EmployeeId").
+    orderBy("EmployeeName desc").
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Employees?$orderby=EmployeeId%2CEmployeeName%20desc", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testUriWithNavigationToManyWithKeyWithSimpleProperty() throws EdmException {
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Managers");
+    EdmEntitySet empEntitySet = edm.getDefaultEntityContainer().getEntitySet("Employees");
+    URI uri = new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment(entitySet).
+    appendKeySegment((EdmProperty)entitySet.getEntityType().getProperty("EmployeeId"), "1").
+    appendNavigationSegment((EdmNavigationProperty)entitySet.getEntityType().getProperty("nm_Employees")).
+    appendKeySegment((EdmProperty)empEntitySet.getEntityType().getProperty("EmployeeId"), "1").
+    appendPropertySegment((EdmProperty)empEntitySet.getEntityType().getProperty("EmployeeName"), "EmployeeName").
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Managers('1')/nm_Employees('1')/EmployeeName", uri.toASCIIString());
+  }
+  
+  @Test
+  public void negTestUriWithNavigationToManyWithSimpleProperty() throws EdmException {
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Managers");
+    EdmEntitySet empEntitySet = edm.getDefaultEntityContainer().getEntitySet("Employees");
+    try {
+      new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+      appendEntitySetSegment(entitySet).
+      appendKeySegment((EdmProperty)entitySet.getEntityType().getProperty("EmployeeId"), "1").
+      appendNavigationSegment((EdmNavigationProperty)entitySet.getEntityType().getProperty("nm_Employees")).
+      appendPropertySegment((EdmProperty)empEntitySet.getEntityType().getProperty("EmployeeName"), "EmployeeName").
+      build();
+    } catch (Exception e) {
+      assertEquals("Can't specify a property at this position", e.getMessage());
+    }
+  }
+  
+  @Test
+  public void testSimpleESWithEncodedKeyUri() throws EdmException {
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Employees");
+    URI uri = new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment(entitySet).
+    appendKeySegment((EdmProperty) entitySet.getEntityType().getProperty("EmployeeId"), "abc/def").
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Employees('abc%2Fdef')", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testCompositeKeysEncodedUri() throws EdmException {
+    EdmEntitySet entitySet = edm.getEntityContainer("Container2").getEntitySet("Photos");
+    Map<EdmProperty, Object> keyMap = new LinkedHashMap<EdmProperty,Object>();
+    keyMap.put((EdmProperty) entitySet.getEntityType().getProperty("Id"), 4);
+    keyMap.put((EdmProperty) entitySet.getEntityType().getProperty("Type"), "foo,foo;");
+    URI uri = new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment(entitySet).
+    appendKeySegment(keyMap).
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Photos(Id=4,Type='foo%2Cfoo%3B')", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testUriWithNavigationToManyWithKeyEncoded() throws EdmException {
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Managers");
+    EdmEntitySet empEntitySet = edm.getDefaultEntityContainer().getEntitySet("Employees");
+    URI uri = new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment(entitySet).
+    appendKeySegment((EdmProperty)entitySet.getEntityType().getProperty("EmployeeId"), "1()*;").
+    appendNavigationSegment((EdmNavigationProperty)entitySet.getEntityType().getProperty("nm_Employees")).
+    appendKeySegment((EdmProperty)empEntitySet.getEntityType().getProperty("EmployeeId"), "@#$%").
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Managers('1%28%29%2A%3B')/nm_Employees('%40%23%24%25')", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testFunctionImportWithEmptyParams() throws EdmException {
+    EdmFunctionImport functionImport = edm.getDefaultEntityContainer().getFunctionImport("AllLocations");
+    Map<EdmParameter, Object> functionImportParams = new HashMap<EdmParameter, Object>();
+    URI uri = new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+        appendFunctionImportSegment(functionImport).appendFunctionImportParameters(functionImportParams).build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/AllLocations", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testFunctionImportWithNullParams() throws EdmException {
+    EdmFunctionImport functionImport = edm.getDefaultEntityContainer().getFunctionImport("AllLocations");
+    URI uri = new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+        appendFunctionImportSegment(functionImport).appendFunctionImportParameters(null).build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/AllLocations", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testFunctionImportWithParams() throws Exception {
+    EdmFunctionImport functionImport = edm.getDefaultEntityContainer().getFunctionImport("EmployeeSearch");
+    Map<EdmParameter, Object> functionImportParams = new HashMap<EdmParameter, Object>();
+    EdmParameter param = edm.getDefaultEntityContainer().getFunctionImport("EmployeeSearch").getParameter("q");
+    functionImportParams.put(param, "Emp1");
+    URI uri = new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+        appendFunctionImportSegment(functionImport).appendFunctionImportParameters(functionImportParams).build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/EmployeeSearch?q='Emp1'", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testFunctionImportWithPathSegmentsAndParams() throws Exception {
+    EdmFunctionImport functionImport = edm.getDefaultEntityContainer().getFunctionImport("EmployeeSearch");
+    Map<EdmParameter, Object> functionImportParams = new HashMap<EdmParameter, Object>();
+    EdmParameter param = edm.getDefaultEntityContainer().getFunctionImport("EmployeeSearch").getParameter("q");
+    functionImportParams.put(param, "Emp1");
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Employees");
+    EdmProperty property = (EdmProperty) entitySet.getEntityType().getProperty("Location");
+    
+    try {
+      new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+          appendFunctionImportSegment(functionImport).appendPropertySegment(property, "Location").
+          appendFunctionImportParameters(functionImportParams).build();
+    } catch (RuntimeException e) {
+      assertEquals("Can't specify a property at this position", e.getMessage());
+    }
+  }
+  
+  @Test
+  public void testUriWithFunctionImportWithKeyEncodedSegment() throws EdmException {
+    EdmFunctionImport functionImport = edm.getDefaultEntityContainer().getFunctionImport("EmployeeSearch");
+    Map<EdmParameter, Object> functionImportParams = new HashMap<EdmParameter, Object>();
+    EdmParameter param = edm.getDefaultEntityContainer().getFunctionImport("EmployeeSearch").getParameter("q");
+    functionImportParams.put(param, "Emp1");
+    Map<EdmProperty, Object> keySegParams = new HashMap<EdmProperty, Object>();
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Employees");
+    keySegParams.put((EdmProperty)entitySet.getEntityType().getProperty("EmployeeId"), "1()*;");
+    
+    URI uri = new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+        appendFunctionImportSegment(functionImport).
+    appendKeySegment(keySegParams).
+    appendFunctionImportParameters(functionImportParams).
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/EmployeeSearch(EmployeeId='1%28%29%2A%3B')?q='Emp1'", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testFunctionImportWithParamsWithNullFacets() throws Exception {
+    EdmFunctionImport functionImport = edm.getDefaultEntityContainer().getFunctionImport("FINullableParameter");
+    Map<EdmParameter, Object> functionImportParams = new HashMap<EdmParameter, Object>();
+    EdmParameter param = edm.getDefaultEntityContainer().getFunctionImport("FINullableParameter").getParameter("Id");
+    functionImportParams.put(param, "1");
+    URI uri = new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+        appendFunctionImportSegment(functionImport).appendFunctionImportParameters(functionImportParams).build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/FINullableParameter?Id='1'", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testFunctionImportWithParamsWithFalseNullFacets() throws Exception {
+    EdmFunctionImport functionImport = edm.getDefaultEntityContainer().getFunctionImport("ManagerPhoto");
+    Map<EdmParameter, Object> functionImportParams = new HashMap<EdmParameter, Object>();
+    EdmParameter param = edm.getDefaultEntityContainer().getFunctionImport("FINullableParameter").getParameter("Id");
+    functionImportParams.put(param, "1");
+    URI uri = new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+        appendFunctionImportSegment(functionImport).appendFunctionImportParameters(functionImportParams).build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/ManagerPhoto?Id='1'", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testFunctionImportWithMultipleParams() throws Exception {
+    EdmFunctionImport functionImport = edm.getDefaultEntityContainer().getFunctionImport("BuildingSearch");
+    Map<EdmParameter, Object> functionImportParams = new LinkedHashMap<EdmParameter, Object>();
+    EdmParameter param1 = edm.getDefaultEntityContainer().getFunctionImport("BuildingSearch").getParameter("q");
+    functionImportParams.put(param1, "1");
+    EdmParameter param2 = edm.getDefaultEntityContainer().getFunctionImport("BuildingSearch").getParameter("r");
+    functionImportParams.put(param2, 1);
+    URI uri = new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+        appendFunctionImportSegment(functionImport).appendFunctionImportParameters(functionImportParams).build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/BuildingSearch?q='1'&r=1", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testFunctionImportWithMultipleParamsWithMoreSegments() throws Exception {
+    EdmFunctionImport functionImport = edm.getDefaultEntityContainer().getFunctionImport("BuildingSearch");
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Buildings");
+    EdmProperty property = (EdmProperty) entitySet.getEntityType().getProperty("Id");
+    EdmNavigationProperty navProperty = (EdmNavigationProperty) entitySet.getEntityType().getProperty("nb_Rooms");
+    Map<EdmParameter, Object> functionImportParams = new LinkedHashMap<EdmParameter, Object>();
+    EdmParameter param1 = edm.getDefaultEntityContainer().getFunctionImport("BuildingSearch").getParameter("q");
+    functionImportParams.put(param1, "1");
+    EdmParameter param2 = edm.getDefaultEntityContainer().getFunctionImport("BuildingSearch").getParameter("r");
+    functionImportParams.put(param2, 1);
+    URI uri = new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+        appendFunctionImportSegment(functionImport).appendKeySegment(property, "1").
+        appendNavigationSegment(navProperty).
+        appendFunctionImportParameters(functionImportParams).build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/BuildingSearch('1')/nb_Rooms?q='1'&r=1", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testFunctionImportWithMultipleParamsWithCount() throws Exception {
+    EdmFunctionImport functionImport = edm.getDefaultEntityContainer().getFunctionImport("BuildingSearch");
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Buildings");
+    EdmProperty property = (EdmProperty) entitySet.getEntityType().getProperty("Id");
+    EdmNavigationProperty navProperty = (EdmNavigationProperty) entitySet.getEntityType().getProperty("nb_Rooms");
+    Map<EdmParameter, Object> functionImportParams = new LinkedHashMap<EdmParameter, Object>();
+    EdmParameter param1 = edm.getDefaultEntityContainer().getFunctionImport("BuildingSearch").getParameter("q");
+    functionImportParams.put(param1, "1");
+    EdmParameter param2 = edm.getDefaultEntityContainer().getFunctionImport("BuildingSearch").getParameter("r");
+    functionImportParams.put(param2, 1);
+    URI uri = new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+        appendFunctionImportSegment(functionImport).appendKeySegment(property, "1").
+        appendNavigationSegment(navProperty).
+        appendCountSegment().
+        appendFunctionImportParameters(functionImportParams).build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/BuildingSearch('1')/nb_Rooms/$count?q='1'&r=1", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testFunctionImportWithCount() throws Exception {
+    EdmFunctionImport functionImport = edm.getDefaultEntityContainer().getFunctionImport("BuildingSearch");
+    Map<EdmParameter, Object> functionImportParams = new LinkedHashMap<EdmParameter, Object>();
+    EdmParameter param1 = edm.getDefaultEntityContainer().getFunctionImport("BuildingSearch").getParameter("q");
+    functionImportParams.put(param1, "1");
+    EdmParameter param2 = edm.getDefaultEntityContainer().getFunctionImport("BuildingSearch").getParameter("r");
+    functionImportParams.put(param2, 1);
+    URI uri = new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+        appendFunctionImportSegment(functionImport).
+        appendCountSegment().
+        appendFunctionImportParameters(functionImportParams).build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/BuildingSearch/$count?q='1'&r=1", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testFunctionImportWithMultipleParamsWithPropertySegment() throws Exception {
+    EdmFunctionImport functionImport = edm.getDefaultEntityContainer().getFunctionImport("BuildingSearch");
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Buildings");
+    EdmProperty property = (EdmProperty) entitySet.getEntityType().getProperty("Id");
+    EdmNavigationProperty navProperty = (EdmNavigationProperty) entitySet.getEntityType().getProperty("nb_Rooms");
+    EdmEntitySet entitySet1 = edm.getDefaultEntityContainer().getEntitySet("Rooms");
+    EdmProperty property1 = (EdmProperty) entitySet1.getEntityType().getProperty("Id");
+    EdmProperty property2 = (EdmProperty) entitySet1.getEntityType().getProperty("Name");
+    Map<EdmParameter, Object> functionImportParams = new LinkedHashMap<EdmParameter, Object>();
+    EdmParameter param1 = edm.getDefaultEntityContainer().getFunctionImport("BuildingSearch").getParameter("q");
+    functionImportParams.put(param1, "1");
+    EdmParameter param2 = edm.getDefaultEntityContainer().getFunctionImport("BuildingSearch").getParameter("r");
+    functionImportParams.put(param2, 1);
+    URI uri = new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+        appendFunctionImportSegment(functionImport).appendKeySegment(property, "1").
+        appendNavigationSegment(navProperty).appendKeySegment(property1, "1").
+        appendPropertySegment(property2, "Name").
+        appendFunctionImportParameters(functionImportParams).build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/BuildingSearch('1')/nb_Rooms('1')/Name?q='1'&r=1", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testFunctionImportWithKeySegment() throws Exception {
+    EdmFunctionImport functionImport = edm.getEntityContainer("Container2").getFunctionImport("PhotoSearch");
+    EdmEntitySet entitySet = edm.getEntityContainer("Container2").getEntitySet("Photos");
+    EdmProperty property = (EdmProperty) entitySet.getEntityType().getProperty("Id");
+    EdmProperty property1 = (EdmProperty) entitySet.getEntityType().getProperty("Type");
+    Map<EdmProperty, Object> keySegments = new LinkedHashMap<EdmProperty, Object>();
+    keySegments.put(property, "1");
+    keySegments.put(property1, "Internal");
+    Map<EdmParameter, Object> functionImportParams = new LinkedHashMap<EdmParameter, Object>();
+    EdmParameter param1 = edm.getEntityContainer("Container2").getFunctionImport("PhotoSearch").getParameter("Id");
+    functionImportParams.put(param1, 1);
+    EdmParameter param2 = edm.getEntityContainer("Container2").getFunctionImport("PhotoSearch").getParameter("Type");
+    functionImportParams.put(param2, "Internal");
+    try {
+    new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+        appendFunctionImportSegment(functionImport).
+        appendKeySegment(keySegments).
+        appendFunctionImportParameters(functionImportParams).build();
+    } catch (RuntimeException e) {
+      assertEquals(e.getMessage(), "Can't specify a key at this position");
+    }
+  }
+  
+  @Test
+  public void testCustomQueryWithSystemQuery() throws Exception {
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Managers");
+    URI uri = new EdmURIBuilderImpl(SERVICE_ROOT_URI).appendEntitySetSegment(entitySet).
+        addCustomQueryOption("x", "y").filter("EmployeeName eq 'Walter Winter'").build();
+    assertEquals("http://host:80/service/Managers?$filter="
+        + "EmployeeName%20eq%20'Walter%20Winter'&x=y", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testServiceDocument() throws Exception {
+    URI uri = new EdmURIBuilderImpl(SERVICE_ROOT_URI).build();
+    assertEquals("http://host:80/service/", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testServiceDocument1() throws Exception {
+    URI uri = new EdmURIBuilderImpl(SERVICE_ROOT_URI_1).build();
+    assertEquals("http://host:80/service/", uri.toASCIIString());
+  }
+  
+  @Test
+  public void addSameFilterOptionTwice() throws EdmException {
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Managers");
+    URI uri = new EdmURIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment(entitySet).
+    appendKeySegment((EdmProperty)entitySet.getEntityType().getProperty("EmployeeId"), "1").
+    appendNavigationSegment((EdmNavigationProperty)entitySet.getEntityType().getProperty("nm_Employees")).
+    addQueryOption(QueryOption.FILTER, "TeamId eq '1'").
+    addQueryOption(QueryOption.FILTER, "TeamId eq '1'").
+    top(2).
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Managers('1')/nm_Employees"
+        + "?$filter=TeamId%20eq%20'1'%2CTeamId%20eq%20'1'&$top=2", uri.toASCIIString());
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/uri/UriBuilderIntegrationTest.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/uri/UriBuilderIntegrationTest.java b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/uri/UriBuilderIntegrationTest.java
new file mode 100644
index 0000000..363ebaf
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/uri/UriBuilderIntegrationTest.java
@@ -0,0 +1,51 @@
+package org.apache.olingo.odata2.client.core.uri;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.net.URI;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.client.api.ODataClient;
+import org.apache.olingo.odata2.testutil.mock.MockFacade;
+import org.junit.Before;
+import org.junit.Test;
+
+public class UriBuilderIntegrationTest {
+
+  protected static final String SERVICE_ROOT_URI = "http://host:80/service/";
+  private Edm edm;
+
+  @Before
+  public void getEdm() throws ODataException {
+    edm = MockFacade.getMockEdm();
+  }
+  
+  @Test
+  public void constructEdmUri() throws EdmException {
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Employees");
+    URI uri = ODataClient.newInstance().edmUriBuilder(SERVICE_ROOT_URI).
+        appendEntitySetSegment(entitySet).
+        appendKeySegment((EdmProperty)entitySet.getEntityType().getProperty("EmployeeId"), "1").
+        appendNavigationSegment((EdmNavigationProperty)entitySet.getEntityType().getProperty("ne_Team")).
+        build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Employees('1')/ne_Team", uri.toASCIIString());
+  }
+  
+  @Test
+  public void constructUri() {
+    URI uri = ODataClient.newInstance().uriBuilder(SERVICE_ROOT_URI).
+        appendEntitySetSegment("Employees").
+        appendKeySegment("1").
+        appendNavigationSegment("ne_Team").
+        build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Employees('1')/ne_Team", uri.toASCIIString());
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/uri/UriBuilderTest.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/uri/UriBuilderTest.java b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/uri/UriBuilderTest.java
new file mode 100644
index 0000000..c9c239e
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/uri/UriBuilderTest.java
@@ -0,0 +1,586 @@
+package org.apache.olingo.odata2.client.core.uri;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.net.URI;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.client.api.uri.QueryOption;
+import org.junit.Test;
+
+public class UriBuilderTest {
+  protected static final String SERVICE_ROOT_URI = "http://host:80/service/";
+  protected static final String SERVICE_ROOT_URI_1 = "http://host:80/service";
+  
+  @Test
+  public void testUriSimpleES() {
+    URI uri = new URIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment("Employees").
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Employees", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testSimpleESWithCountUri1() {
+    URI uri = new URIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment("Employees").
+    appendCountSegment().
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Employees/$count", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testSimpleESWithCountUri2() {
+    URI uri = new URIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment("Managers").
+    appendKeySegment("1").
+    appendNavigationSegment("nm_Employees").
+    appendCountSegment().
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Managers('1')/nm_Employees/$count", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testSimpleESWithCountAndFilter() {
+    URI uri = new URIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment("Managers").
+    appendKeySegment("1").
+    appendNavigationSegment("nm_Employees").
+    appendCountSegment().
+    addQueryOption(QueryOption.FILTER, "TeamId eq '1'").
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Managers('1')/nm_Employees/"
+        + "$count?$filter=TeamId%20eq%20'1'", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testMetadataUri() {
+    URI uri = new URIBuilderImpl(SERVICE_ROOT_URI).
+    appendMetadataSegment().
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/$metadata", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testSimpleESWithKeyUri() {
+    URI uri = new URIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment("Employees").
+    appendKeySegment("1").
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Employees('1')", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testSimpleESWithKeyUri1() {
+    URI uri = new URIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment("Employees").
+    appendKeySegment(1).
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Employees(1)", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testCompositeKeysUri() {
+    Map<String, Object> keyMap = new LinkedHashMap<String,Object>();
+    keyMap.put("Id", 4);
+    keyMap.put("Type", "foo");
+    URI uri = new URIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment("Photos").
+    appendKeySegment(keyMap).
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Photos(Id=4,Type='foo')", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testFilterUri() {
+    URI uri = new URIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment("Photos").
+    filter("Name eq 'Photo 1'").
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Photos?$filter=Name%20eq%20'Photo%201'", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testTopUri1() {
+    URI uri = new URIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment("Photos").
+    top(2).
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Photos?$top=2", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testTopUri2() {
+    URI uri = new URIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment("Managers").
+    appendKeySegment("1").
+    appendNavigationSegment("nm_Employees").
+    addQueryOption(QueryOption.FILTER, "TeamId eq '1'").
+    top(2).
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Managers('1')/nm_Employees"
+        + "?$filter=TeamId%20eq%20'1'&$top=2", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testSkipUri() {
+    URI uri = new URIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment("Photos").
+    skip(2).
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Photos?$skip=2", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testUriWithQueryOptions() {
+    URI uri = new URIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment("Photos").
+    filter("Name eq 'Photo 1'").
+    top(2).
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Photos?$filter=Name%20eq%20'Photo%201'&$top=2", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testUriWithNavigationSegment2() {
+    URI uri = new URIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment("Managers").
+    appendKeySegment("1").
+    appendNavigationSegment("nm_Employees").
+    appendKeySegment("1").
+    appendNavigationSegment("ne_Team").
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Managers('1')/nm_Employees('1')/ne_Team", uri.toASCIIString());
+  }
+  @Test
+  public void testUriWithSimplePropertySegment() {
+    URI uri = new URIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment("Employees").
+    appendKeySegment("1").
+    appendPropertySegment("EmployeeName").
+    appendValueSegment().
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Employees('1')/EmployeeName/$value", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testUriWithComplexPropertySegment() {
+    URI uri = new URIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment("Employees").
+    appendKeySegment("1").
+    appendPropertySegment("Location").
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Employees('1')/Location", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testUriWithComplexPropertySegment1() {
+    URI uri = new URIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment("Employees").
+    appendKeySegment("1").
+    appendPropertySegment("Location").
+    appendPropertySegment("City").
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Employees('1')/Location/City", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testUriWithOrderby() {
+    URI uri = new URIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment("Managers").
+    appendKeySegment("1").
+    appendNavigationSegment("nm_Employees").
+    orderBy("EmployeeId").
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Managers('1')/nm_Employees?$orderby=EmployeeId", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testUriWithOrderbyAndFormat() {
+    URI uri = new URIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment("Managers").
+    appendKeySegment("1").
+    appendNavigationSegment("nm_Employees").
+    orderBy("EmployeeId").
+    format("application/json").
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Managers('1')/nm_Employees"
+        + "?$orderby=EmployeeId&$format=application%2Fjson", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testUriWithSelect() {
+    URI uri = new URIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment("Managers").
+    appendKeySegment("1").
+    appendNavigationSegment("nm_Employees").
+    select("EmployeeId", "EmployeeName", "RoomId", "TeamId").
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Managers('1')/nm_Employees"
+        + "?$select=EmployeeId%2CEmployeeName%2CRoomId%2CTeamId", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testUriWithSelectAndFilter() {
+    URI uri = new URIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment("Managers").
+    appendKeySegment("1").
+    appendNavigationSegment("nm_Employees").
+    filter("EmployeeId eq 1").
+    select("EmployeeId", "EmployeeName", "RoomId", "TeamId").
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Managers('1')/nm_Employees?$filter="
+        + "EmployeeId%20eq%201&$select=EmployeeId%2CEmployeeName%2CRoomId%2CTeamId", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testUriWithExpand() {
+    URI uri = new URIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment("Managers").
+    appendKeySegment("1").
+    expand("nm_Employees").
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Managers('1')?$expand=nm_Employees", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testUriWithExpandAndFilter() {
+    URI uri = new URIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment("Managers").
+    expand("nm_Employees").
+    filter("EmployeeName eq 'Walter Winter'").
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Managers?$expand=nm_Employees&$filter="
+        + "EmployeeName%20eq%20'Walter%20Winter'", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testUriWithCustomQueryOption() {
+    URI uri = new URIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment("Employees").
+    top(2).
+    addCustomQueryOption("x", "y").
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Employees?$top=2&x=y", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testUriWithCustomQueryOptionWithFormat() {
+    URI uri = new URIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment("Employees").
+    top(2).
+    addCustomQueryOption("x", "y").
+    format("application/json").
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Employees?$top=2&$format=application%2Fjson&x=y", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testUriWithFilters() {
+    URI uri = new URIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment("Managers").
+    filter("EmployeeId ge '1' and EmployeeId le '10'").
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Managers?$filter=EmployeeId%20ge%20'1'%20"
+        + "and%20EmployeeId%20le%20'10'", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testUriWithDuplicateExpands() {
+    URI uri = new URIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment("Managers").
+    expand("nm_Employees").
+    expand("nm_Employees").
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Managers?$expand=nm_Employees%2Cnm_Employees", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testUriWithTwoCustomQueryOptions() {
+    URI uri = new URIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment("Employees").
+    top(2).
+    addCustomQueryOption("x", "y").
+    addCustomQueryOption("z", "y").
+    format("application/json").
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Employees?$top=2&$"
+        + "format=application%2Fjson&x=y&z=y", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testUriWithDuplicateOrderby() {
+    URI uri = new URIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment("Managers").
+    orderBy("EmployeeId").
+    orderBy("EmployeeId").
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Managers?$orderby=EmployeeId%2CEmployeeId", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testUriWithTwoOrderby() {
+    URI uri = new URIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment("Employees").
+    orderBy("EmployeeId").
+    orderBy("EmployeeName desc").
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Employees?$orderby=EmployeeId%2CEmployeeName%20desc", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testUriWithNavigationToManyWithKeyWithSimpleProperty() {
+    URI uri = new URIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment("Managers").
+    appendKeySegment("1").
+    appendNavigationSegment("nm_Employees").
+    appendKeySegment("1").
+    appendPropertySegment("EmployeeName").
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Managers('1')/nm_Employees('1')/EmployeeName", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testSimpleESWithEncodedKeyUri() {
+    URI uri = new URIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment("Employees").
+    appendKeySegment("abc/def").
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Employees('abc%2Fdef')", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testCompositeKeysEncodedUri() {
+    Map<String, Object> keyMap = new LinkedHashMap<String,Object>();
+    keyMap.put("Id", 4);
+    keyMap.put("Type", "foo,foo;");
+    URI uri = new URIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment("Photos").
+    appendKeySegment(keyMap).
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Photos(Id=4,Type='foo%2Cfoo%3B')", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testUriWithNavigationToManyWithKeyEncoded() throws EdmException {
+    URI uri = new URIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment("Managers").
+    appendKeySegment("1()*;").
+    appendNavigationSegment("nm_Employees").
+    appendKeySegment("@#$%").
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Managers('1%28%29%2A%3B')/nm_Employees('%40%23%24%25')", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testFunctionImportWithEmptyParams() throws EdmException {
+    Map<String, Object> functionImportParams = new HashMap<String, Object>();
+    URI uri = new URIBuilderImpl(SERVICE_ROOT_URI).
+        appendFunctionImportSegment("AllLocations").appendFunctionImportParameters(functionImportParams).build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/AllLocations", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testFunctionImportWithNullParams() throws EdmException {
+    URI uri = new URIBuilderImpl(SERVICE_ROOT_URI).
+        appendFunctionImportSegment("AllLocations").appendFunctionImportParameters(null).build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/AllLocations", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testFunctionImportWithParams() throws Exception {
+    Map<String, Object> functionImportParams = new HashMap<String, Object>();
+    functionImportParams.put("q", "Emp1");
+    URI uri = new URIBuilderImpl(SERVICE_ROOT_URI).
+        appendFunctionImportSegment("EmployeeSearch").appendFunctionImportParameters(functionImportParams).build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/EmployeeSearch?q='Emp1'", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testFunctionImportWithParamsWithNullFacets() throws Exception {
+    Map<String, Object> functionImportParams = new HashMap<String, Object>();
+    functionImportParams.put("Id", "1");
+    URI uri = new URIBuilderImpl(SERVICE_ROOT_URI).
+        appendFunctionImportSegment("FINullableParameter").appendFunctionImportParameters(functionImportParams).build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/FINullableParameter?Id='1'", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testFunctionImportWithParamsWithFalseNullFacets() throws Exception {
+    Map<String, Object> functionImportParams = new HashMap<String, Object>();
+    functionImportParams.put("Id", "1");
+    URI uri = new URIBuilderImpl(SERVICE_ROOT_URI).
+        appendFunctionImportSegment("ManagerPhoto").appendFunctionImportParameters(functionImportParams).build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/ManagerPhoto?Id='1'", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testFunctionImportWithMultipleParams() throws Exception {
+    Map<String, Object> functionImportParams = new LinkedHashMap<String, Object>();
+    functionImportParams.put("q", "1");
+    functionImportParams.put("r", 1);
+    URI uri = new URIBuilderImpl(SERVICE_ROOT_URI).
+        appendFunctionImportSegment("BuildingSearch").appendFunctionImportParameters(functionImportParams).build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/BuildingSearch?q='1'&r=1", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testFunctionImportWithMultipleParamsWithMoreSegments() throws Exception {
+    Map<String, Object> functionImportParams = new LinkedHashMap<String, Object>();
+    functionImportParams.put("q", "1");
+    functionImportParams.put("r", 1);
+    URI uri = new URIBuilderImpl(SERVICE_ROOT_URI).
+        appendFunctionImportSegment("BuildingSearch").appendKeySegment("1").
+        appendNavigationSegment("nb_Rooms").
+        appendFunctionImportParameters(functionImportParams).build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/BuildingSearch('1')/nb_Rooms?q='1'&r=1", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testFunctionImportWithMultipleParamsWithCount() throws Exception {
+    Map<String, Object> functionImportParams = new LinkedHashMap<String, Object>();
+    functionImportParams.put("q", "1");
+    functionImportParams.put("r", 1);
+    URI uri = new URIBuilderImpl(SERVICE_ROOT_URI).
+        appendFunctionImportSegment("BuildingSearch").appendKeySegment("1").
+        appendNavigationSegment("nb_Rooms").
+        appendCountSegment().
+        appendFunctionImportParameters(functionImportParams).build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/BuildingSearch('1')/nb_Rooms/$count?q='1'&r=1", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testFunctionImportWithCount() throws Exception {
+    Map<String, Object> functionImportParams = new LinkedHashMap<String, Object>();
+    functionImportParams.put("q", "1");
+    functionImportParams.put("r", 1);
+    URI uri = new URIBuilderImpl(SERVICE_ROOT_URI).
+        appendFunctionImportSegment("BuildingSearch").
+        appendCountSegment().
+        appendFunctionImportParameters(functionImportParams).build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/BuildingSearch/$count?q='1'&r=1", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testFunctionImportWithMultipleParamsWithPropertySegment() throws Exception {
+    Map<String, Object> functionImportParams = new LinkedHashMap<String, Object>();
+    functionImportParams.put("q", "1");
+    functionImportParams.put("r", 1);
+    URI uri = new URIBuilderImpl(SERVICE_ROOT_URI).
+        appendFunctionImportSegment("BuildingSearch").appendKeySegment("1").
+        appendNavigationSegment("nb_Rooms").appendKeySegment("1").
+        appendPropertySegment("Name").
+        appendFunctionImportParameters(functionImportParams).build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/BuildingSearch('1')/nb_Rooms('1')/Name?q='1'&r=1", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testFunctionImportWithKeySegment() throws Exception {
+    Map<String, Object> keySegments = new LinkedHashMap<String, Object>();
+    keySegments.put("Id", "1");
+    keySegments.put("Type", "Internal");
+    Map<String, Object> functionImportParams = new LinkedHashMap<String, Object>();
+    functionImportParams.put("Id", 1);
+    functionImportParams.put("Type", "Internal");
+    try {
+    new URIBuilderImpl(SERVICE_ROOT_URI).
+        appendFunctionImportSegment("PhotoSearch").
+        appendKeySegment(keySegments).
+        appendFunctionImportParameters(functionImportParams).build();
+    } catch (RuntimeException e) {
+      assertEquals(e.getMessage(), "Can't specify a key at this position");
+    }
+  }
+  
+  @Test
+  public void testCustomQueryWithSystemQuery() throws Exception {
+    URI uri = new URIBuilderImpl(SERVICE_ROOT_URI).appendEntitySetSegment("Managers").
+        addCustomQueryOption("x", "y").filter("EmployeeName eq 'Walter Winter'").build();
+    assertEquals("http://host:80/service/Managers?$filter="
+        + "EmployeeName%20eq%20'Walter%20Winter'&x=y", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testUriWithOnlyCustomQueryOption() throws EdmException {
+    URI uri = new URIBuilderImpl(SERVICE_ROOT_URI_1).
+    addCustomQueryOption("x", "y").
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service?x=y", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testServiceDocument() throws Exception {
+    URI uri = new URIBuilderImpl(SERVICE_ROOT_URI).build();
+    assertEquals("http://host:80/service/", uri.toASCIIString());
+  }
+  
+  @Test
+  public void testServiceDocument1() throws Exception {
+    URI uri = new URIBuilderImpl(SERVICE_ROOT_URI_1).build();
+    assertEquals("http://host:80/service/", uri.toASCIIString());
+  }
+  
+  @Test
+  public void addSameFilterOptionTwice() throws EdmException {
+    URI uri = new URIBuilderImpl(SERVICE_ROOT_URI).
+    appendEntitySetSegment("Managers").
+    appendKeySegment("1").
+    appendNavigationSegment("nm_Employees").
+    addQueryOption(QueryOption.FILTER, "TeamId eq '1'").
+    addQueryOption(QueryOption.FILTER, "TeamId eq '1'").
+    top(2).
+    build();
+    assertNotNull(uri);
+    assertEquals("http://host:80/service/Managers('1')/nm_Employees"
+        + "?$filter=TeamId%20eq%20'1'%2CTeamId%20eq%20'1'&$top=2", uri.toASCIIString());
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/uri/UriInfoTest.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/uri/UriInfoTest.java b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/uri/UriInfoTest.java
new file mode 100644
index 0000000..e515206
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/uri/UriInfoTest.java
@@ -0,0 +1,168 @@
+package org.apache.olingo.odata2.client.core.uri;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertNull;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.api.uri.PathSegment;
+import org.apache.olingo.odata2.api.uri.UriInfo;
+import org.apache.olingo.odata2.api.uri.UriNotMatchingException;
+import org.apache.olingo.odata2.api.uri.UriSyntaxException;
+import org.apache.olingo.odata2.client.api.ODataClient;
+import org.apache.olingo.odata2.core.ODataPathSegmentImpl;
+import org.apache.olingo.odata2.core.uri.UriInfoImpl;
+import org.apache.olingo.odata2.testutil.mock.MockFacade;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class UriInfoTest {
+
+  private static Edm edm;
+  
+  @BeforeClass
+  public static void getEdm() throws ODataException, EdmException {
+    edm = MockFacade.getMockEdm();
+  }
+  
+  @Test
+  public void everythingInitial() throws Exception {
+    UriInfoImpl result = parse("/");
+
+    assertEquals(Collections.emptyList(), result.getKeyPredicates());
+    assertEquals(Collections.emptyList(), result.getTargetKeyPredicates());
+    assertEquals(Collections.emptyList(), result.getNavigationSegments());
+    assertEquals(Collections.emptyList(), result.getPropertyPath());
+    assertEquals(Collections.emptyList(), result.getExpand());
+    assertEquals(Collections.emptyList(), result.getSelect());
+    assertEquals(Collections.emptyMap(), result.getFunctionImportParameters());
+    assertEquals(Collections.emptyMap(), result.getCustomQueryOptions());
+    assertNull(result.getEntityContainer());
+    assertNull(result.getStartEntitySet());
+    assertNull(result.getTargetEntitySet());
+    assertNull(result.getFunctionImport());
+    assertNull(result.getTargetType());
+    assertNull(result.getFormat());
+    assertNull(result.getFilter());
+    assertNull(result.getInlineCount());
+    assertNull(result.getOrderBy());
+    assertNull(result.getSkipToken());
+    assertNull(result.getSkip());
+    assertNull(result.getTop());
+  }
+
+  @Test
+  public void allInitial() throws Exception {
+    UriInfoImpl result = parse("/Employees");
+
+    assertEquals(Collections.emptyList(), result.getKeyPredicates());
+    assertEquals(Collections.emptyList(), result.getTargetKeyPredicates());
+    assertEquals(Collections.emptyList(), result.getNavigationSegments());
+    assertEquals(Collections.emptyList(), result.getPropertyPath());
+    assertEquals(Collections.emptyList(), result.getExpand());
+    assertEquals(Collections.emptyList(), result.getSelect());
+    assertEquals(Collections.emptyMap(), result.getFunctionImportParameters());
+    assertEquals(Collections.emptyMap(), result.getCustomQueryOptions());
+  }
+
+  @Test
+  public void someInitial() throws Exception {
+    UriInfoImpl result = parse("/Employees('1')");
+
+    assertNotSame(Collections.emptyList(), result.getKeyPredicates());
+    assertNotSame(Collections.emptyList(), result.getTargetKeyPredicates());
+
+    assertEquals(Collections.emptyList(), result.getNavigationSegments());
+    assertEquals(Collections.emptyList(), result.getPropertyPath());
+    assertEquals(Collections.emptyList(), result.getExpand());
+    assertEquals(Collections.emptyList(), result.getSelect());
+    assertEquals(Collections.emptyMap(), result.getFunctionImportParameters());
+    assertEquals(Collections.emptyMap(), result.getCustomQueryOptions());
+  }
+
+  @Test
+  public void someInitial2() throws Exception {
+    UriInfoImpl result = parse("/Employees('1')/ne_Manager");
+
+    assertNotSame(Collections.emptyList(), result.getKeyPredicates());
+    assertNotSame(Collections.emptyList(), result.getNavigationSegments());
+
+    assertEquals(Collections.emptyList(), result.getTargetKeyPredicates());
+    assertEquals(Collections.emptyList(), result.getPropertyPath());
+    assertEquals(Collections.emptyList(), result.getExpand());
+    assertEquals(Collections.emptyList(), result.getSelect());
+    assertEquals(Collections.emptyMap(), result.getFunctionImportParameters());
+    assertEquals(Collections.emptyMap(), result.getCustomQueryOptions());
+  }
+  
+  /**
+   * Parse the URI part after an OData service root, given as string.
+   * Query parameters can be included.
+   * @param uri the URI part
+   * @return a {@link UriInfoImpl} instance containing the parsed information
+   */
+  private UriInfoImpl parse(final String uri) throws UriSyntaxException, UriNotMatchingException, EdmException {
+    final String[] path = uri.split("\\?", -1);
+    if (path.length > 2) {
+      throw new UriSyntaxException(UriSyntaxException.URISYNTAX);
+    }
+
+    final List<PathSegment> pathSegments = getPathSegments(path[0]);
+    Map<String, List<String>> queryParameters;
+    if (path.length == 2) {
+      queryParameters = getQueryParameters(unescape(path[1]));
+    } else {
+      queryParameters = new HashMap<String, List<String>>();
+    }
+
+    UriInfo result = ODataClient.newInstance().parseUri(edm, pathSegments, queryParameters);
+
+    return (UriInfoImpl) result;
+  }
+  
+  private List<PathSegment> getPathSegments(final String uri) throws UriSyntaxException {
+    List<PathSegment> pathSegments = new ArrayList<PathSegment>();
+    for (final String segment : uri.split("/", -1)) {
+      final String unescapedSegment = unescape(segment);
+      PathSegment oDataSegment = new ODataPathSegmentImpl(unescapedSegment, null);
+      pathSegments.add(oDataSegment);
+    }
+    return pathSegments;
+  }
+  
+  private Map<String, List<String>> getQueryParameters(final String uri) {
+    Map<String, List<String>> allQueryParameters = new HashMap<String, List<String>>();
+
+    for (final String option : uri.split("&")) {
+      final String[] keyAndValue = option.split("=");
+      List<String> list = allQueryParameters.containsKey(keyAndValue[0]) ?
+          allQueryParameters.get(keyAndValue[0]) : new LinkedList<String>();
+
+      list.add(keyAndValue.length == 2 ? keyAndValue[1] : "");
+
+      allQueryParameters.put(keyAndValue[0], list);
+    }
+
+    return allQueryParameters;
+  }
+  
+  private String unescape(final String s) throws UriSyntaxException {
+    try {
+      return new URI(s).getPath();
+    } catch (URISyntaxException e) {
+      throw new UriSyntaxException(UriSyntaxException.NOTEXT);
+    }
+  }
+
+}


[11/24] olingo-odata2 git commit: [OLINGO-1253]Client Module for Olingo v2

Posted by ar...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/deserializer/XmlMetadataDeserializerTest.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/deserializer/XmlMetadataDeserializerTest.java b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/deserializer/XmlMetadataDeserializerTest.java
new file mode 100644
index 0000000..daf7a5c
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/deserializer/XmlMetadataDeserializerTest.java
@@ -0,0 +1,1904 @@
+/*******************************************************************************
+ * 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.client.core.ep.deserializer;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.List;
+
+import javax.xml.stream.XMLStreamException;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmAction;
+import org.apache.olingo.odata2.api.edm.EdmAnnotationAttribute;
+import org.apache.olingo.odata2.api.edm.EdmAnnotationElement;
+import org.apache.olingo.odata2.api.edm.EdmAnnotations;
+import org.apache.olingo.odata2.api.edm.EdmAssociation;
+import org.apache.olingo.odata2.api.edm.EdmAssociationSet;
+import org.apache.olingo.odata2.api.edm.EdmAssociationSetEnd;
+import org.apache.olingo.odata2.api.edm.EdmComplexType;
+import org.apache.olingo.odata2.api.edm.EdmConcurrencyMode;
+import org.apache.olingo.odata2.api.edm.EdmContentKind;
+import org.apache.olingo.odata2.api.edm.EdmEntityContainer;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmEntityType;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmFacets;
+import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
+import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeKind;
+import org.apache.olingo.odata2.api.edm.provider.EdmProvider;
+import org.apache.olingo.odata2.api.ep.EntityProvider;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.processor.ODataResponse;
+import org.apache.olingo.odata2.client.api.ODataClient;
+import org.apache.olingo.odata2.client.api.edm.ClientEdm;
+import org.apache.olingo.odata2.client.api.edm.EdmDataServices;
+import org.apache.olingo.odata2.client.api.edm.EdmSchema;
+import org.apache.olingo.odata2.client.api.edm.EdmUsing;
+import org.apache.olingo.odata2.client.core.edm.EdmMetadataAssociationEnd;
+import org.apache.olingo.odata2.testutil.helper.StringHelper;
+import org.apache.olingo.odata2.testutil.mock.EdmTestProvider;
+import org.junit.Test;
+
+public class XmlMetadataDeserializerTest extends AbstractXmlDeserializerTest {
+
+  public XmlMetadataDeserializerTest(final StreamWriterImplType type) {
+    super(type);
+  }
+
+  private static final String DEFAULT_VALUE = "Photo";
+  private static final String FC_TARGET_PATH = "Содержание";
+  private static final String FC_NS_URI = "http://localhost";
+  private static final String FC_NS_PREFIX = "ру";
+  private static final Boolean FC_KEEP_IN_CONTENT = Boolean.FALSE;
+  private static final String NAMESPACE = "RefScenario";
+  private static final String NAMESPACE2 = "RefScenario2";
+  private static final String NAMESPACE3 = "RefScenario3";
+  private static final String MIME_TYPE = "image/jpeg";
+  private static final String ASSOCIATION = "ManagerEmployees";
+  private static final int MAX_LENGTH = 4;
+
+  private final String[] propertyNames = { "EmployeeId", "EmployeeName", "Location" };
+
+  private final String xml = "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\"" + Edm.NAMESPACE_EDMX_2007_06 + "\">"
+      + "<edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\"" + Edm.NAMESPACE_M_2007_08 + "\">"
+      + "<Schema Namespace=\"" + NAMESPACE + "\" xmlns=\"" + Edm.NAMESPACE_EDM_2008_09 + "\">"
+      + "<EntityType Name= \"Employee\" m:HasStream=\"true\">" + "<Key><PropertyRef Name=\"EmployeeId\"/></Key>"
+      + "<Property Name=\"" + propertyNames[0] + "\" Type=\"Edm.String\" Nullable=\"false\"/>" + "<Property Name=\""
+      + propertyNames[1] + "\" Type=\"Edm.String\" m:FC_TargetPath=\"SyndicationTitle\"/>" + "<Property Name=\""
+      + propertyNames[2] + "\" Type=\"RefScenario.c_Location\" Nullable=\"false\"/>" + "</EntityType>"
+      + "<ComplexType Name=\"c_Location\">" + "<Property Name=\"Country\" Type=\"Edm.String\"/>" + "</ComplexType>"
+      + "</Schema>" + "</edmx:DataServices>" + "</edmx:Edmx>";
+  
+  private final String customxml = "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\"" + Edm.NAMESPACE_EDMX_2007_06 + "\">"
+      + "<edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\"" + Edm.NAMESPACE_M_2007_08 + "\">"
+      + "<Schema Namespace=\"" + NAMESPACE + "\" xmlns=\"" + Edm.NAMESPACE_EDM_2008_09 + "\">"
+      + "<EntityType Name= \"Employee\" m:FC_TargetPath=\"SyndicationTitle\" m:HasStream=\"true\">"
+      + "<Key><PropertyRef Name=\"EmployeeId\"/></Key>"
+      + "<Property Name=\"" + propertyNames[0] + "\" Type=\"Edm.String\" Nullable=\"false\"/>" + "<Property Name=\""
+      + propertyNames[1] + "\" Type=\"Edm.String\" m:FC_TargetPath=\"SyndicationTitle\"/>" + "<Property Name=\""
+      + propertyNames[2] + "\" Type=\"RefScenario.c_Location\" Nullable=\"false\"/>" + "</EntityType>"
+      + "<ComplexType Name=\"c_Location\">" + "<Property Name=\"Country\" Type=\"Edm.String\"/>" + "</ComplexType>"
+      + "</Schema>" + "</edmx:DataServices>" + "</edmx:Edmx>";
+
+  private final String xml2 = "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\"" + Edm.NAMESPACE_EDMX_2007_06
+      + "\" xmlns:prefix=\"namespace\">" + "<edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\""
+      + Edm.NAMESPACE_M_2007_08 + "\">" + "<Schema Namespace=\"" + NAMESPACE + "\" xmlns=\""
+      + Edm.NAMESPACE_EDM_2008_01 + "\">" + "<prefix:schemaElement>text3</prefix:schemaElement>"
+      + "<EntityType Name= \"Employee\" m:HasStream=\"true\">" + "<Key><PropertyRef Name=\"EmployeeId\"/></Key>"
+      + "<Property Name=\"" + propertyNames[0] + "\" Type=\"Edm.String\" Nullable=\"false\"/>" + "<Property Name=\""
+      + propertyNames[1] + "\" Type=\"Edm.String\" m:FC_TargetPath=\"SyndicationTitle\"/>" + "<Property Name=\""
+      + propertyNames[2] + "\" Type=\"RefScenario.c_Location\" Nullable=\"false\"/>" + "</EntityType>"
+      + "<ComplexType Name=\"c_Location\">" + "<Property Name=\"Country\" Type=\"Edm.String\"/>" + "</ComplexType>"
+      + "</Schema>" + "</edmx:DataServices>" + "</edmx:Edmx>";
+
+  private final String xmlWithBaseType = "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\"" + Edm.NAMESPACE_EDMX_2007_06
+      + "\">" + "<edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\"" + Edm.NAMESPACE_M_2007_08 + "\">"
+      + "<Schema Namespace=\"" + NAMESPACE + "\" xmlns=\"" + Edm.NAMESPACE_EDM_2008_09 + "\">"
+      + "<EntityType Name= \"Employee\">" + "<Key><PropertyRef Name=\"EmployeeId\"/></Key>" + "<Property Name=\""
+      + propertyNames[0] + "\" Type=\"Edm.String\" Nullable=\"false\"/>" + "<Property Name=\"" + propertyNames[1]
+      + "\" Type=\"Edm.String\" m:FC_TargetPath=\"SyndicationTitle\"/>" + "<Property Name=\"" + propertyNames[2]
+      + "\" Type=\"RefScenario.c_Location\" Nullable=\"false\"/>" + "</EntityType>"
+      + "<EntityType Name=\"Manager\" BaseType=\"RefScenario.Employee\" m:HasStream=\"true\">" + "</EntityType>"
+      + "<ComplexType Name=\"c_Location\">" + "<Property Name=\"Country\" Type=\"Edm.String\"/>" + "</ComplexType>"
+      + "</Schema>" + "</edmx:DataServices>" + "</edmx:Edmx>";
+
+  private final String xmlWithAssociation =
+      "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\""
+          + Edm.NAMESPACE_EDMX_2007_06
+          + "\">"
+          + "<edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\""
+          + Edm.NAMESPACE_M_2007_08
+          + "\">"
+          + "<Schema Namespace=\""
+          + NAMESPACE
+          + "\" xmlns=\""
+          + Edm.NAMESPACE_EDM_2008_09
+          + "\">"
+          + "<EntityType Name= \"Employee\">"
+          + "<Key><PropertyRef Name=\"EmployeeId\"/></Key>"
+          + "<Property Name=\""
+          + propertyNames[0]
+          + "\" Type=\"Edm.String\" Nullable=\"false\"/>"
+          + "<NavigationProperty Name=\"ne_Manager\" Relationship=\"RefScenario.ManagerEmployees\" " +
+          "FromRole=\"r_Employees\" ToRole=\"r_Manager\" />"
+          + "</EntityType>"
+          + "<EntityType Name=\"Manager\" BaseType=\"RefScenario.Employee\" m:HasStream=\"true\">"
+          + "<NavigationProperty Name=\"nm_Employees\" Relationship=\"RefScenario.ManagerEmployees\" " +
+          "FromRole=\"r_Manager\" ToRole=\"r_Employees\" />"
+          + "</EntityType>" + "<Association Name=\"" + ASSOCIATION + "\">"
+          + "<End Type=\"RefScenario.Employee\" Multiplicity=\"*\" Role=\"r_Employees\">"
+          + "<OnDelete Action=\"Cascade\"/>" + "</End>"
+          + "<End Type=\"RefScenario.Manager\" Multiplicity=\"1\" Role=\"r_Manager\"/>" + "</Association>"
+          + "</Schema>" + "<Schema Namespace=\"" + NAMESPACE2 + "\" xmlns=\"" + Edm.NAMESPACE_EDM_2008_09 + "\">"
+          + "<EntityContainer Name=\"Container1\" m:IsDefaultEntityContainer=\"true\">"
+          + "<EntitySet Name=\"Employees\" EntityType=\"RefScenario.Employee\"/>"
+          + "<EntitySet Name=\"Managers\" EntityType=\"RefScenario.Manager\"/>" + "<AssociationSet Name=\""
+          + ASSOCIATION + "\" Association=\"RefScenario." + ASSOCIATION + "\">"
+          + "<End EntitySet=\"Managers\" Role=\"r_Manager\"/>" + "<End EntitySet=\"Employees\" Role=\"r_Employees\"/>"
+          + "</AssociationSet>" + "</EntityContainer>" + "</Schema>" + "</edmx:DataServices>" + "</edmx:Edmx>";
+
+  private final String xmlWithTwoSchemas = "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\"" + Edm.NAMESPACE_EDMX_2007_06
+      + "\">" + "<edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\"" + Edm.NAMESPACE_M_2007_08 + "\">"
+      + "<Schema Namespace=\"" + NAMESPACE + "\" xmlns=\"" + Edm.NAMESPACE_EDM_2008_09 + "\">"
+      + "<EntityType Name= \"Employee\">" + "<Key><PropertyRef Name=\"EmployeeId\"/></Key>" + "<Property Name=\""
+      + propertyNames[0] + "\" Type=\"Edm.String\" Nullable=\"false\"/>" + "<Property Name=\"" + propertyNames[1]
+      + "\" Type=\"Edm.String\"/>" + "</EntityType>" + "</Schema>" + "<Schema Namespace=\"" + NAMESPACE2
+      + "\" xmlns=\"" + Edm.NAMESPACE_EDM_2008_09 + "\">" + "<EntityType Name= \"Photo\">"
+      + "<Key><PropertyRef Name=\"Id\"/></Key>"
+      + "<Property Name=\"Id\" Type=\"Edm.Int32\" Nullable=\"false\" ConcurrencyMode=\"Fixed\" MaxLength=\""
+      + MAX_LENGTH + "\"/>" + "<Property Name=\"Name\" Type=\"Edm.String\" Unicode=\"true\" DefaultValue=\""
+      + DEFAULT_VALUE
+      + "\" FixedLength=\"false\"/>" + "<Property Name=\"BinaryData\" Type=\"Edm.Binary\" m:MimeType=\"" + MIME_TYPE
+      + "\"/>" + "<Property Name=\"Содержание\" Type=\"Edm.String\" m:FC_TargetPath=\"" + FC_TARGET_PATH
+      + "\" m:FC_NsUri=\"" + FC_NS_URI + "\"" + " m:FC_NsPrefix=\"" + FC_NS_PREFIX + "\" m:FC_KeepInContent=\""
+      + FC_KEEP_IN_CONTENT + "\" m:FC_ContentKind=\"text\" >" + "</Property>" + "</EntityType>" + "</Schema>"
+      + "</edmx:DataServices>" + "</edmx:Edmx>";
+
+  private final String xmlWithStringValueForMaxLengthFacet = "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\""
+      + Edm.NAMESPACE_EDMX_2007_06
+      + "\">" + "<edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\"" + Edm.NAMESPACE_M_2007_08 + "\">"
+      + "<Schema Namespace=\"" + NAMESPACE2 + "\" xmlns=\"" + Edm.NAMESPACE_EDM_2008_09 + "\">"
+      + "<EntityType Name= \"Photo\"><Key><PropertyRef Name=\"Id\"/></Key><Property Name=\"Id\" Type=\"Edm.Int32\" " +
+      "Nullable=\"false\" MaxLength=\"Max\"/><Property Name=\"Name\" Type=\"Edm.Int32\" MaxLength=\"max\"/>"
+      + "</EntityType></Schema></edmx:DataServices></edmx:Edmx>";
+  private final String edmxRefFor1680364709 = 
+      "<edmx:Edmx xmlns:edmx=\"http://schemas.microsoft.com/ado/2007/06/edmx\" " +
+      "xmlns:m=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\" xmlns:sap=\"" +
+      "http://www.sap.com/Protocols/SAPData\" Version=\"1.0\">" +
+      "<edmx:Reference xmlns:edmx=\"http://docs.oasis-open.org/odata/ns/edmx\" " +
+      "Uri=\"https://host:port/sap/opu/odata/IWFND/CATALOGSERVICE;v=2/Vocabularies"+
+      "(TechnicalName='%2FIWBEP%2FVOC_COMMON'"+
+      ",Version='0001',SAP__Origin='')/$value\">" +
+      "<edmx:Include Alias=\"Common\" Namespace=\"com.sap.vocabularies.Common.v1\"/>" +
+      "</edmx:Reference>" + 
+      "</edmx:Edmx>";
+  
+  @Test
+  public void twoEdmxWithValidation() throws Exception {
+    InputStream reader = createStreamReader(edmxRefFor1680364709); 
+    EdmDataServices result = ODataClient.newInstance().readMetadata(reader, true);   
+    assertNotNull(result);
+
+  }
+  
+  @Test
+  public void twoEdmxWithoutValidation() throws Exception {
+    InputStream reader = createStreamReader(edmxRefFor1680364709); 
+    EdmDataServices result = ODataClient.newInstance().readMetadata(reader, true);
+    assertNotNull(result);
+
+  }
+  @Test
+  public void testMetadataDokumentWithWhitepaces() throws Exception {
+    final String metadata = ""
+        + "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\"" + Edm.NAMESPACE_EDMX_2007_06 + "\">"
+        + "   <edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\"" + Edm.NAMESPACE_M_2007_08 + "\">"
+        + "       <Schema Namespace=\"" + NAMESPACE2 + "\" xmlns=\"" + Edm.NAMESPACE_EDM_2008_09 + "\">"
+        + "           <EntityType Name= \"Photo\">"
+        + "               <Key> "
+        + "                 <PropertyRef Name=\"Id\" />"
+        + "               </Key>"
+        + "               <Property Name=\"Id\" Type=\"Edm.Int16\" Nullable=\"false\" />"
+        + "               <MyAnnotation xmlns=\"http://company.com/odata\">   "
+        + "                 <child> value1</child>"
+        + "                 <child>value2</child>"
+        + "               </MyAnnotation>"
+        + "           </EntityType>"
+        + "       </Schema>"
+        + "  </edmx:DataServices>"
+        + "</edmx:Edmx>";
+
+    InputStream reader = createStreamReader(metadata); 
+    EdmDataServices result = ODataClient.newInstance().readMetadata(reader, true);
+    assertEquals(1, result.getEdm().getSchemas().size());
+    List<EdmEntityType> entityTypes = result.getEdm().getSchemas().get(0).getEntityTypes();
+    assertEquals(1, entityTypes.size());
+    EdmEntityType entityType = entityTypes.get(0);
+    EdmAnnotations annotation= entityType.getAnnotations();
+    List<EdmAnnotationElement> annotationElements = annotation.getAnnotationElements();
+    assertEquals(1, annotationElements.size());
+    EdmAnnotationElement annotationElement = annotationElements.get(0);
+    List<EdmAnnotationElement> childElements = annotationElement.getChildElements();
+    assertEquals(2, childElements.size());
+
+    assertEquals(" value1", childElements.get(0).getText());
+    assertEquals("value2", childElements.get(1).getText());
+  }
+
+  @Test
+  public void testMetadataDokumentWithWhitepacesMultiline() throws Exception {
+    final String metadata = ""
+        + "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\"" + Edm.NAMESPACE_EDMX_2007_06 + "\">"
+        + "   <edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\"" + Edm.NAMESPACE_M_2007_08 + "\">"
+        + "       <Schema Namespace=\"" + NAMESPACE2 + "\" xmlns=\"" + Edm.NAMESPACE_EDM_2008_09 + "\">"
+        + "           <EntityType Name= \"Photo\">"
+        + "               <Key> "
+        + "                 <PropertyRef Name=\"Id\" />"
+        + "               </Key>"
+        + "               <Property Name=\"Id\" Type=\"Edm.Int16\" Nullable=\"false\" />"
+        + "               <MyAnnotation xmlns=\"http://company.com/odata\">   "
+        + "                 <child> value1\n"
+        + "                 long long long multiline attribute</child>"
+        + "                 <child>value2</child>"
+        + "               </MyAnnotation>"
+        + "           </EntityType>"
+        + "       </Schema>"
+        + "  </edmx:DataServices>"
+        + "</edmx:Edmx>";
+
+    XmlMetadataDeserializer parser = new XmlMetadataDeserializer();
+    InputStream reader = createStreamReader(metadata);
+    EdmDataServices result = parser.readMetadata(reader, true);
+
+    assertEquals(1, result.getEdm().getSchemas().size());
+    List<EdmEntityType> entityTypes = result.getEdm().getSchemas().get(0).getEntityTypes();
+    assertEquals(1, entityTypes.size());
+    EdmEntityType entityType = entityTypes.get(0);
+    EdmAnnotations annotations = entityType.getAnnotations();
+    List<EdmAnnotationElement> annotationElements = annotations.getAnnotationElements();
+    assertEquals(1, annotationElements.size());
+    EdmAnnotationElement annotationElement = annotationElements.get(0);
+    List<EdmAnnotationElement> childElements = annotationElement.getChildElements();
+    assertEquals(2, childElements.size());
+
+    assertEquals(" value1\n" +
+        "                 long long long multiline attribute", childElements.get(0).getText());
+    assertEquals("value2", childElements.get(1).getText());
+  }
+
+  @Test
+  public void testMetadataDokumentWithWhitepaces2() throws Exception {
+    final String metadata = ""
+        + "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\"" + Edm.NAMESPACE_EDMX_2007_06 + "\">"
+        + "   <edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\"" + Edm.NAMESPACE_M_2007_08 + "\">"
+        + "       <Schema Namespace=\"" + NAMESPACE2 + "\" xmlns=\"" + Edm.NAMESPACE_EDM_2008_09 + "\">"
+        + "           <EntityType Name= \"Photo\">"
+        + "               <Key> "
+        + "                 <PropertyRef Name=\"Id\" />"
+        + "               </Key>"
+        + "               <Property Name=\"Id\" Type=\"Edm.Int16\" Nullable=\"false\" />"
+        + "               <MyAnnotation xmlns=\"http://company.com/odata\">   "
+        + "                 <child> value1"
+        + "</child></MyAnnotation>"
+        + "           </EntityType>"
+        + "       </Schema>"
+        + "  </edmx:DataServices>"
+        + "</edmx:Edmx>";
+
+    XmlMetadataDeserializer parser = new XmlMetadataDeserializer();
+    InputStream reader = createStreamReader(metadata);
+    EdmDataServices result = parser.readMetadata(reader, true);
+
+    assertEquals(1, result.getEdm().getSchemas().size());
+    List<EdmEntityType> entityTypes = result.getEdm().getSchemas().get(0).getEntityTypes();
+    assertEquals(1, entityTypes.size());
+    EdmEntityType entityType = entityTypes.get(0);
+    EdmAnnotations annotations = entityType.getAnnotations();
+    List<EdmAnnotationElement> annotationElements = annotations.getAnnotationElements();
+    assertEquals(1, annotationElements.size());
+    EdmAnnotationElement annotationElement = annotationElements.get(0);
+    List<EdmAnnotationElement> childElements = annotationElement.getChildElements();
+    assertEquals(1, childElements.size());
+
+    assertEquals(" value1", childElements.get(0).getText());
+  }
+
+  @Test
+  public void ODATAJAVA_77_testMetadataDokumentWithMultiLevelEntityType() throws Exception {
+    final String metadata = ""
+        + "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\"" + Edm.NAMESPACE_EDMX_2007_06 + "\">"
+        + "   <edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\"" + Edm.NAMESPACE_M_2007_08 + "\">"
+        + "       <Schema Namespace=\"" + NAMESPACE2 + "\" xmlns=\"" + Edm.NAMESPACE_EDM_2008_09 + "\">"
+        + "         <EntityType Name= \"Parameter\">"
+        + "               <Key> "
+        + "                 <PropertyRef Name=\"Id\" />"
+        + "               </Key>"
+        + "               <Property Name=\"Id\" Type=\"Edm.Int16\" Nullable=\"false\" />"
+        + "           </EntityType>"
+        + "           <EntityType Name= \"ConfigParameter\" BaseType= \"RefScenario2.Parameter\" />"
+        + "           <EntityType Name= \"DataConfigParameter\" BaseType= \"RefScenario2.ConfigParameter\" />"
+        + "           <EntityType Name= \"StringDataConfigParameter\" BaseType= \"RefScenario2.DataConfigParameter\" />"
+        + "       </Schema>"
+        + "  </edmx:DataServices>"
+        + "</edmx:Edmx>";
+
+    XmlMetadataDeserializer parser = new XmlMetadataDeserializer();
+    InputStream reader = createStreamReader(metadata);
+    EdmDataServices result = parser.readMetadata(reader, true);
+
+    assertEquals(1, result.getEdm().getSchemas().size());
+    List<EdmEntityType> entityTypes = result.getEdm().getSchemas().get(0).getEntityTypes();
+    assertEquals(4, entityTypes.size());
+
+  }
+
+  @Test
+  public void testMultiplebaseType() throws Exception {
+    final String metadata = ""
+        + "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\"" + Edm.NAMESPACE_EDMX_2007_06 + "\">"
+        + "   <edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\"" + Edm.NAMESPACE_M_2007_08 + "\">"
+        + "       <Schema Namespace=\"" + NAMESPACE2 + "\" xmlns=\"" + Edm.NAMESPACE_EDM_2008_09 + "\">"
+        + "        <Using Namespace=\"com.sap.banking.common.endpoint.v1_0.beans\" Alias=\"common\"/>"
+        + "        <Using Namespace=\"com.sap.banking.messages.endpoint.v1_0.beans\" Alias=\"messages\"/>" 
+        + "         <EntityType Name= \"StringDataConfigParameter\" BaseType= \"RefScenario2.DataConfigParameter\" />"
+        + "           <EntityType Name= \"DataConfigParameter\" BaseType= \"RefScenario2.ConfigParameter\" >"
+        + "               <Key> "
+        + "                 <PropertyRef Name=\"Name\" />"
+        + "               </Key>"
+        + "               <Property Name=\"Name\" Type=\"Edm.String\" Nullable=\"false\" />"
+        + "           </EntityType>"
+        + "           <EntityType Name= \"ConfigParameter\" BaseType= \"RefScenario2.Parameter\" >"
+        + "              <Property Name=\"ConfigName\" Type=\"Edm.String\" Nullable=\"false\" />"
+        + "            </EntityType>"
+        + "         <EntityType Name= \"Parameter\">"
+        + "               <Key> "
+        + "                 <PropertyRef Name=\"Id\" />"
+        + "               </Key>"
+        + "               <Property Name=\"Id\" Type=\"Edm.Int16\" Nullable=\"false\" />"
+        + "           </EntityType>"
+        + "       </Schema>"
+        + "  </edmx:DataServices>"
+        + "</edmx:Edmx>";
+
+    XmlMetadataDeserializer parser = new XmlMetadataDeserializer();
+    InputStream reader = createStreamReader(metadata);
+    EdmDataServices result = parser.readMetadata(reader, true);
+
+    assertEquals(1, result.getEdm().getSchemas().size());
+    List<EdmEntityType> entityTypes = result.getEdm().getSchemas().get(0).getEntityTypes();
+    assertEquals(4, entityTypes.size());
+    for(EdmEntityType entityType:entityTypes){
+      if(entityType.getName().equalsIgnoreCase("StringDataConfigParameter")){
+        assertEquals(3, entityType.getPropertyNames().size());
+        assertEquals("Name", entityType.getPropertyNames().get(0));  
+        assertEquals("ConfigName", entityType.getPropertyNames().get(1));  
+        assertEquals("Id", entityType.getPropertyNames().get(2)); 
+      }else if(entityType.getName().equalsIgnoreCase("DataConfigParameter")){
+        assertEquals(3, entityType.getPropertyNames().size());
+        assertEquals("Name", entityType.getPropertyNames().get(0));  
+        assertEquals("ConfigName", entityType.getPropertyNames().get(1));  
+        assertEquals("Id", entityType.getPropertyNames().get(2)); 
+      }else if(entityType.getName().equalsIgnoreCase("ConfigParameter")){
+        assertEquals(2, entityType.getPropertyNames().size());
+        assertEquals("ConfigName", entityType.getPropertyNames().get(0));  
+        assertEquals("Id", entityType.getPropertyNames().get(1));    
+      }else if(entityType.getName().equalsIgnoreCase("Parameter")){
+        assertEquals(1, entityType.getPropertyNames().size());
+        assertEquals("Id", entityType.getPropertyNames().get(0));
+      }
+      
+    }
+
+  }
+  
+  @Test
+  public void testUsing() throws Exception {
+    final String metadata = ""
+        + "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\"" + Edm.NAMESPACE_EDMX_2007_06 + "\">"
+        + "   <edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\"" + Edm.NAMESPACE_M_2007_08 + "\">"
+        + "       <Schema Namespace=\"" + NAMESPACE2 + "\" xmlns=\"" + Edm.NAMESPACE_EDM_2008_09 + "\">"
+        + "        <Using Namespace=\"com.sap.banking.common.endpoint.v1_0.beans\" Alias=\"common\"/>"
+        + "        <Using Namespace=\"com.sap.banking.messages.endpoint.v1_0.beans\" Alias=\"messages\"/>"
+        + "       </Schema>"
+        + "  </edmx:DataServices>"
+        + "</edmx:Edmx>";
+
+    XmlMetadataDeserializer parser = new XmlMetadataDeserializer();
+    InputStream reader = createStreamReader(metadata);
+    EdmDataServices result = parser.readMetadata(reader, false);
+
+    assertEquals(1, result.getEdm().getSchemas().size());
+    List<EdmUsing> using = result.getEdm().getSchemas().get(0).getUsings();
+    assertEquals(2, using.size());
+    
+
+  }
+  
+  @Test
+  public void testMultiplebaseTypeOrderChange() throws Exception {
+    final String metadata = ""
+        + "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\"" + Edm.NAMESPACE_EDMX_2007_06 + "\">"
+        + "   <edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\"" + Edm.NAMESPACE_M_2007_08 + "\">"
+        + "       <Schema Namespace=\"" + NAMESPACE2 + "\" xmlns=\"" + Edm.NAMESPACE_EDM_2008_09 + "\">"
+        + "           <EntityType Name= \"ConfigParameter\" BaseType= \"RefScenario2.Parameter\" >"
+        + "              <Property Name=\"ConfigName\" Type=\"Edm.String\" Nullable=\"false\" />"
+        + "            </EntityType>"
+        + "           <EntityType Name= \"DataConfigParameter\" BaseType= \"RefScenario2.ConfigParameter\" >"
+        + "               <Key> "
+        + "                 <PropertyRef Name=\"Name\" />"
+        + "               </Key>"
+        + "               <Property Name=\"Name\" Type=\"Edm.String\" Nullable=\"false\" />"
+        + "           </EntityType>"
+        + "         <EntityType Name= \"Parameter\">"
+        + "               <Key> "
+        + "                 <PropertyRef Name=\"Id\" />"
+        + "               </Key>"
+        + "               <Property Name=\"Id\" Type=\"Edm.Int16\" Nullable=\"false\" />"
+        + "           </EntityType>"
+        + "         <EntityType Name= \"StringDataConfigParameter\" BaseType= \"RefScenario2.DataConfigParameter\" />"
+        + "         <EntityType Name= \"AnotherDataConfigParameter\" BaseType= \"RefScenario2.DataConfigParameter\" />"
+        + "       </Schema>"
+        + "  </edmx:DataServices>"
+        + "</edmx:Edmx>";
+
+    XmlMetadataDeserializer parser = new XmlMetadataDeserializer();
+    InputStream reader = createStreamReader(metadata);
+    EdmDataServices result = parser.readMetadata(reader, true);
+
+    assertEquals(1, result.getEdm().getSchemas().size());
+    List<EdmEntityType> entityTypes = result.getEdm().getSchemas().get(0).getEntityTypes();
+    assertEquals(5, entityTypes.size());
+    for(EdmEntityType entityType:entityTypes){
+      if(entityType.getName().equalsIgnoreCase("StringDataConfigParameter")){
+        assertEquals(3, entityType.getPropertyNames().size());
+        assertEquals("Name", entityType.getPropertyNames().get(0));  
+        assertEquals("ConfigName", entityType.getPropertyNames().get(1));  
+        assertEquals("Id", entityType.getPropertyNames().get(2)); 
+      }else if(entityType.getName().equalsIgnoreCase("DataConfigParameter")){
+        assertEquals(3, entityType.getPropertyNames().size());
+        assertEquals("Name", entityType.getPropertyNames().get(0));  
+        assertEquals("ConfigName", entityType.getPropertyNames().get(1));  
+        assertEquals("Id", entityType.getPropertyNames().get(2)); 
+      }else if(entityType.getName().equalsIgnoreCase("ConfigParameter")){
+        assertEquals(2, entityType.getPropertyNames().size());
+        assertEquals("ConfigName", entityType.getPropertyNames().get(0));  
+        assertEquals("Id", entityType.getPropertyNames().get(1));    
+      }else if(entityType.getName().equalsIgnoreCase("Parameter")){
+        assertEquals(1, entityType.getPropertyNames().size());
+        assertEquals("Id", entityType.getPropertyNames().get(0));
+      }else if(entityType.getName().equalsIgnoreCase("AnotherDataConfigParameter")){
+        assertEquals(3, entityType.getPropertyNames().size());
+        assertEquals("Name", entityType.getPropertyNames().get(0));  
+        assertEquals("ConfigName", entityType.getPropertyNames().get(1));  
+        assertEquals("Id", entityType.getPropertyNames().get(2)); 
+      }
+      
+    }
+
+  }
+  
+  @Test
+  public void ODATAJAVA_77_testBaseTypeKey() throws Exception {
+    final String metadata = ""
+        + "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\"" + Edm.NAMESPACE_EDMX_2007_06 + "\">"
+        + "   <edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\"" + Edm.NAMESPACE_M_2007_08 + "\">"
+        + "       <Schema Namespace=\"" + NAMESPACE2 + "\" xmlns=\"" + Edm.NAMESPACE_EDM_2008_09 + "\">"
+        + "         <EntityType Name= \"Parameter\">"
+        + "               <Key> "
+        + "                 <PropertyRef Name=\"Id\" />"
+        + "               </Key>"
+        + "               <Property Name=\"Id\" Type=\"Edm.Int16\" Nullable=\"false\" />"
+        + "           </EntityType>"
+        + "           <EntityType Name= \"ConfigParameter\" BaseType= \"RefScenario2.Parameter\" />"
+        + "           <EntityType Name= \"DataConfigParameter\" BaseType= \"RefScenario2.ConfigParameter\" >"
+        + "               <Key> "
+        + "                 <PropertyRef Name=\"Name\" />"
+        + "               </Key>"
+        + "               <Property Name=\"Name\" Type=\"Edm.String\" Nullable=\"false\" />"
+        + "           </EntityType>"
+        + "           <EntityType Name= \"StringDataConfigParameter\" BaseType= \"RefScenario2.DataConfigParameter\" />"
+        + "       </Schema>"
+        + "  </edmx:DataServices>"
+        + "</edmx:Edmx>";
+
+    XmlMetadataDeserializer parser = new XmlMetadataDeserializer();
+    InputStream reader = createStreamReader(metadata);
+    EdmDataServices result = parser.readMetadata(reader, true);
+
+    assertEquals(1, result.getEdm().getSchemas().size());
+    List<EdmEntityType> entityTypes = result.getEdm().getSchemas().get(0).getEntityTypes();
+    assertEquals(4, entityTypes.size());
+
+  }
+
+  @Test
+  public void ODATAJAVA_77_testEntityTypeKey() throws Exception {
+    final String metadata = ""
+        + "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\"" + Edm.NAMESPACE_EDMX_2007_06 + "\">"
+        + "   <edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\"" + Edm.NAMESPACE_M_2007_08 + "\">"
+        + "       <Schema Namespace=\"" + NAMESPACE2 + "\" xmlns=\"" + Edm.NAMESPACE_EDM_2008_09 + "\">"
+        + "         <EntityType Name= \"Parameter\">"
+        + "               <Key> "
+        + "                 <PropertyRef Name=\"Id\" />"
+        + "               </Key>"
+        + "               <Property Name=\"Id\" Type=\"Edm.Int16\" Nullable=\"false\" />"
+        + "           </EntityType>"
+        + "           <EntityType Name= \"ConfigParameter\" BaseType= \"RefScenario2.Parameter\" />"
+        + "           <EntityType Name= \"DataConfigParameter\" BaseType= \"RefScenario2.ConfigParameter\" />"
+        + "           <EntityType Name= \"StringDataConfigParameter\" BaseType= \"RefScenario2.DataConfigParameter\" >"
+        + "               <Key> "
+        + "                 <PropertyRef Name=\"Name\" />"
+        + "               </Key>"
+        + "               <Property Name=\"Name\" Type=\"Edm.String\" Nullable=\"false\" />"
+        + "           </EntityType>"
+        + "       </Schema>"
+        + "  </edmx:DataServices>"
+        + "</edmx:Edmx>";
+
+    XmlMetadataDeserializer parser = new XmlMetadataDeserializer();
+    InputStream reader = createStreamReader(metadata);
+    EdmDataServices result = parser.readMetadata(reader, true);
+
+    assertEquals(1, result.getEdm().getSchemas().size());
+    List<EdmEntityType> entityTypes = result.getEdm().getSchemas().get(0).getEntityTypes();
+    assertEquals(4, entityTypes.size());
+
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void ODATAJAVA_77_ExceptionScenario() throws Exception {
+    final String metadata = ""
+        + "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\"" + Edm.NAMESPACE_EDMX_2007_06 + "\">"
+        + "   <edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\"" + Edm.NAMESPACE_M_2007_08 + "\">"
+        + "       <Schema Namespace=\"" + NAMESPACE2 + "\" xmlns=\"" + Edm.NAMESPACE_EDM_2008_09 + "\">"
+        + "           <EntityType Name= \"ConfigParameter\" BaseType= \"RefScenario2.Parameter\" />"
+        + "           <EntityType Name= \"DataConfigParameter\" BaseType= \"RefScenario2.ConfigParameter\" />"
+        + "           <EntityType Name= \"StringDataConfigParameter\" BaseType= \"RefScenario2.DataConfigParameter\" />"
+        + "         <EntityType Name= \"Parameter\">"
+        + "            <Property Name=\"Id\" Type=\"Edm.Int16\" Nullable=\"false\" />"
+        + "           </EntityType>"
+        + "       </Schema>"
+        + "  </edmx:DataServices>"
+        + "</edmx:Edmx>";
+
+    XmlMetadataDeserializer parser = new XmlMetadataDeserializer();
+    InputStream reader = createStreamReader(metadata);
+    parser.readMetadata(reader, true);
+  }
+
+  @Test
+  public void stringValueForMaxLegthFacet() throws Exception {
+    XmlMetadataDeserializer parser = new XmlMetadataDeserializer();
+    InputStream reader = createStreamReader(xmlWithStringValueForMaxLengthFacet);
+    EdmDataServices result = parser.readMetadata(reader, true);
+
+    List<String> properties = result.getEdm().getSchemas().get(0).getEntityTypes().get(0).getKeyPropertyNames();
+    assertEquals(1, properties.size());
+
+    EdmProperty property = (EdmProperty) result.getEdm().getSchemas().get(0).getEntityTypes().get(0).getProperty("Id");
+    EdmFacets facets = property.getFacets();
+    assertEquals(new Integer(Integer.MAX_VALUE), facets.getMaxLength());
+
+    property = (EdmProperty) result.getEdm().getSchemas().get(0).getEntityTypes().get(0).getProperty("Name");
+    facets = property.getFacets();
+    assertEquals(new Integer(Integer.MAX_VALUE), facets.getMaxLength());
+  }
+
+
+  @Test
+  public void test() throws XMLStreamException, 
+  EntityProviderException, EdmException, UnsupportedEncodingException {
+    int i = 0;
+    XmlMetadataDeserializer parser = new XmlMetadataDeserializer();
+    InputStream reader = createStreamReader(xml);
+    EdmDataServices result = parser.readMetadata(reader, true);
+    assertEquals("2.0", result.getDataServiceVersion());
+    for (EdmSchema schema : result.getEdm().getSchemas()) {
+      assertEquals(NAMESPACE, schema.getNamespace());
+      assertEquals(1, schema.getEntityTypes().size());
+      assertEquals("Employee", schema.getEntityTypes().get(0).getName());
+      assertEquals(Boolean.TRUE, schema.getEntityTypes().get(0).hasStream());
+      for (EdmProperty propertyRef : schema.getEntityTypes().get(0).getKeyProperties()) {
+        assertEquals("EmployeeId", propertyRef.getName());
+      }
+      for (String name : schema.getEntityTypes().get(0).getPropertyNames()) {
+        assertEquals(propertyNames[i], name);
+        EdmProperty property = (EdmProperty) schema.getEntityTypes().get(0).getProperty(name);
+        if ("Location".equals(property.getName())) {
+          EdmProperty cProperty =  property;
+          assertEquals(NAMESPACE, cProperty.getType().getNamespace());
+          assertEquals("c_Location", cProperty.getType().getName());
+        } else if ("EmployeeName".equals(property.getName())) {
+          assertNotNull(property.getCustomizableFeedMappings());
+          assertEquals("SyndicationTitle", property.getCustomizableFeedMappings().getFcTargetPath());
+          assertNull(property.getCustomizableFeedMappings().getFcContentKind());
+        }
+        i++;
+      }
+      assertEquals(1, schema.getComplexTypes().size());
+      assertEquals("c_Location", schema.getComplexTypes().get(0).getName());
+    }
+  }
+
+  @Test
+  public void testCustom() throws XMLStreamException, 
+  EntityProviderException, EdmException, UnsupportedEncodingException {
+    XmlMetadataDeserializer parser = new XmlMetadataDeserializer();
+    InputStream reader = createStreamReader(customxml);
+    EdmDataServices result = parser.readMetadata(reader, true);
+    assertEquals("2.0", result.getDataServiceVersion());
+    EdmSchema schema = result.getEdm().getSchemas().get(0);
+    assertNotNull(result.getEdm().getSchemas().get(0).getEntityTypes().get(0).getCustomizableFeedMappings());
+    assertEquals("SyndicationTitle", schema.getEntityTypes().get(0).getCustomizableFeedMappings().getFcTargetPath());
+
+  }
+  @Test
+  public void testOtherEdmNamespace() throws XMLStreamException, 
+  EntityProviderException, EdmException, UnsupportedEncodingException {
+    int i = 0;
+    XmlMetadataDeserializer parser = new XmlMetadataDeserializer();
+    InputStream reader = createStreamReader(xml2);
+    EdmDataServices result = parser.readMetadata(reader, true);
+    assertEquals("2.0", result.getDataServiceVersion());
+    for (EdmSchema schema : result.getEdm().getSchemas()) {
+      assertEquals(NAMESPACE, schema.getNamespace());
+      assertEquals(1, schema.getEntityTypes().size());
+      assertEquals("Employee", schema.getEntityTypes().get(0).getName());
+      for (EdmProperty propertyRef : schema.getEntityTypes().get(0).getKeyProperties()) {
+        assertEquals("EmployeeId", propertyRef.getName());
+      }
+      for (String name : schema.getEntityTypes().get(0).getPropertyNames()) {
+        EdmEntityType entity = schema.getEntityTypes().get(0);
+        assertEquals(propertyNames[i], name);
+        if ("Location".equals(name)) {
+          EdmProperty cProperty = (EdmProperty) entity.getProperty(name);
+          assertEquals("c_Location", cProperty.getType().getName());
+        } else if ("EmployeeName".equals(name)) {
+          assertNotNull(((EdmProperty) entity.getProperty(name)).getCustomizableFeedMappings());
+        }
+        i++;
+      }
+      for (EdmAnnotationElement annoElement : schema.getAnnotationElements()) {
+        assertEquals("prefix", annoElement.getPrefix());
+        assertEquals("namespace", annoElement.getNamespace());
+        assertEquals("schemaElement", annoElement.getName());
+        assertEquals("text3", annoElement.getText());
+      }
+    }
+  }
+
+  @Test
+  public void testBaseType() throws XMLStreamException, 
+  EntityProviderException, EdmException, UnsupportedEncodingException {
+    int i = 0;
+    XmlMetadataDeserializer parser = new XmlMetadataDeserializer();
+    InputStream reader = createStreamReader(xmlWithBaseType);
+    EdmDataServices result = parser.readMetadata(reader, true);
+    assertEquals("2.0", result.getDataServiceVersion());
+    for (EdmSchema schema : result.getEdm().getSchemas()) {
+      assertEquals(NAMESPACE, schema.getNamespace());
+      assertEquals(2, schema.getEntityTypes().size());
+      assertEquals("Employee", schema.getEntityTypes().get(0).getName());
+      for (String propertyRef : schema.getEntityTypes().get(0).getKeyPropertyNames()) {
+           assertEquals("EmployeeId", propertyRef);
+      }
+      for (String property : schema.getEntityTypes().get(0).getPropertyNames()) {
+        assertEquals(propertyNames[i], property);
+        i++;
+      }
+
+    }
+  }
+
+  @Test
+  public void testComplexTypeWithBaseType() throws XMLStreamException, 
+  EntityProviderException, EdmException, UnsupportedEncodingException {
+    final String xml =
+        "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\"" + Edm.NAMESPACE_EDMX_2007_06 + "\">"
+            + "<edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\"" + Edm.NAMESPACE_M_2007_08 + "\">"
+            + "<Schema Namespace=\"" + NAMESPACE + "\" Alias=\"RS\"  xmlns=\"" + Edm.NAMESPACE_EDM_2008_09 + "\">"
+            + "<EntityType Name= \"Employee\" m:HasStream=\"true\">" + "<Key><PropertyRef Name=\"EmployeeId\"/></Key>"
+            + "<Property Name=\"" + propertyNames[0] + "\" Type=\"Edm.String\" Nullable=\"false\"/>"
+            + "<Property Name=\"" + propertyNames[2] + "\" Type=\"RefScenario.c_Location\" Nullable=\"false\"/>"
+            + "</EntityType>" + "<ComplexType Name=\"c_BaseType_for_Location\" Abstract=\"true\">"
+            + "<Property Name=\"Country\" Type=\"Edm.String\"/>" + "</ComplexType>"
+            + "<ComplexType Name=\"c_Location\" BaseType=\"RefScenario.c_BaseType_for_Location\">" + "</ComplexType>"
+            + "<ComplexType Name=\"c_Other_Location\" BaseType=\"RS.c_BaseType_for_Location\">" + "</ComplexType>"
+            + "</Schema>"
+            + "</edmx:DataServices>" + "</edmx:Edmx>";
+    XmlMetadataDeserializer parser = new XmlMetadataDeserializer();
+    InputStream reader = createStreamReader(xml);
+    EdmDataServices result = parser.readMetadata(reader, true);
+    assertEquals("2.0", result.getDataServiceVersion());
+    for (EdmSchema schema : result.getEdm().getSchemas()) {
+      for (EdmComplexType complexType : schema.getComplexTypes()) {
+        if ("c_Location".equals(complexType.getName())) {
+          assertNotNull(complexType.getBaseType());
+          assertEquals("c_BaseType_for_Location", complexType.getBaseType().getName());
+          assertEquals("RefScenario", complexType.getBaseType().getNamespace());
+        } else if ("c_Other_Location".equals(complexType.getName())) {
+          assertNotNull(complexType.getBaseType());
+          assertEquals("c_BaseType_for_Location", complexType.getBaseType().getName());
+          assertEquals("RefScenario", complexType.getBaseType().getNamespace());
+        } else if ("c_BaseType_for_Location".equals(complexType.getName())) {
+          assertNotNull(complexType);
+        } else {
+          assertTrue(false);
+        }
+      }
+
+    }
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void testComplexTypeWithInvalidBaseType() throws XMLStreamException, 
+  EntityProviderException, EdmException, UnsupportedEncodingException {
+    final String xml =
+        "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\"" + Edm.NAMESPACE_EDMX_2007_06 + "\">"
+            + "<edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\"" + Edm.NAMESPACE_M_2007_08 + "\">"
+            + "<Schema Namespace=\"" + NAMESPACE + "\" xmlns=\"" + Edm.NAMESPACE_EDM_2008_09 + "\">"
+            + "<EntityType Name= \"Employee\" m:HasStream=\"true\">" + "<Key><PropertyRef Name=\"EmployeeId\"/></Key>"
+            + "<Property Name=\"" + propertyNames[0] + "\" Type=\"Edm.String\" Nullable=\"false\"/>"
+            + "<Property Name=\"" + propertyNames[2] + "\" Type=\"RefScenario.c_Location\" Nullable=\"false\"/>"
+            + "</EntityType>" + "<ComplexType Name=\"c_BaseType_for_Location\" Abstract=\"true\">"
+            + "<Property Name=\"Country\" Type=\"Edm.String\"/>" + "</ComplexType>"
+            + "<ComplexType Name=\"c_Location\" BaseType=\"RefScenario.Employee\">" + "</ComplexType>" + "</Schema>"
+            + "</edmx:DataServices>" + "</edmx:Edmx>";
+    XmlMetadataDeserializer parser = new XmlMetadataDeserializer();
+    InputStream reader = createStreamReader(xml);
+    parser.readMetadata(reader, true);
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void testComplexTypeWithInvalidBaseType2() throws XMLStreamException, 
+  EntityProviderException, EdmException, UnsupportedEncodingException {
+    final String xml =
+        "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\"" + Edm.NAMESPACE_EDMX_2007_06 + "\">"
+            + "<edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\"" + Edm.NAMESPACE_M_2007_08 + "\">"
+            + "<Schema Namespace=\"" + NAMESPACE + "\" xmlns=\"" + Edm.NAMESPACE_EDM_2008_09 + "\">"
+            + "<EntityType Name= \"Employee\" m:HasStream=\"true\">" + "<Key><PropertyRef Name=\"EmployeeId\"/></Key>"
+            + "<Property Name=\"" + propertyNames[0] + "\" Type=\"Edm.String\" Nullable=\"false\"/>"
+            + "<Property Name=\"" + propertyNames[2] + "\" Type=\"RefScenario.c_Location\" Nullable=\"false\"/>"
+            + "</EntityType>" + "<ComplexType Name=\"c_BaseType_for_Location\" Abstract=\"true\">"
+            + "<Property Name=\"Country\" Type=\"Edm.String\"/>" + "</ComplexType>"
+            + "<ComplexType Name=\"c_Location\" BaseType=\"c_BaseType_for_Location\">" + "</ComplexType>" + "</Schema>"
+            + "</edmx:DataServices>" + "</edmx:Edmx>";
+    XmlMetadataDeserializer parser = new XmlMetadataDeserializer();
+    InputStream reader = createStreamReader(xml);
+    parser.readMetadata(reader, true);
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void testMissingEdmxCloseTag() throws XMLStreamException, 
+  EntityProviderException, EdmException, UnsupportedEncodingException {
+    final String xml = "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\"" + Edm.NAMESPACE_EDMX_2007_06 + "\">"
+        + "<edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\"" + Edm.NAMESPACE_M_2007_08 + "\">"
+        + "<Schema Namespace=\"" + NAMESPACE + "\" xmlns=\"" + Edm.NAMESPACE_EDM_2008_09 + "\">"
+        + "<EntityType Name= \"Employee\" m:HasStream=\"true\">" + "<Key><PropertyRef Name=\"EmployeeId\"/></Key>"
+        + "<Property Name=\"" + propertyNames[0] + "\" Type=\"Edm.String\" Nullable=\"false\"/>" + "<Property Name=\""
+        + propertyNames[1] + "\" Type=\"Edm.String\" m:FC_TargetPath=\"SyndicationTitle\"/>" + "<Property Name=\""
+        + propertyNames[2] + "\" Type=\"RefScenario.c_Location\" Nullable=\"false\"/>" + "</EntityType>"
+        + "<ComplexType Name=\"c_Location\">" + "<Property Name=\"Country\" Type=\"Edm.String\"/>" + "</ComplexType>"
+        + "</Schema>" + "</edmx:DataServices>";
+
+    XmlMetadataDeserializer parser = new XmlMetadataDeserializer();
+    InputStream reader = createStreamReader(xml);
+    parser.readMetadata(reader, true);
+  }
+
+  @Test
+  public void testAssociation() throws XMLStreamException, 
+  EntityProviderException, EdmException, UnsupportedEncodingException {
+    XmlMetadataDeserializer parser = new XmlMetadataDeserializer();
+    InputStream reader = createStreamReader(xmlWithAssociation);
+    EdmDataServices result = parser.readMetadata(reader, true);
+    assertEquals("2.0", result.getDataServiceVersion());
+    assertEquals("EdmImpl", result.getEdm().toString());
+    for (EdmSchema schema : result.getEdm().getSchemas()) {
+      assertEquals(schema.getNamespace()+"."+schema.getAlias(), schema.toString());
+      for (EdmEntityType entityType : schema.getEntityTypes()) {
+        assertEquals("RefScenario."+entityType.getName(), entityType.toString());
+        if ("Manager".equals(entityType.getName())) {
+          assertEquals("RefScenario", entityType.getBaseType().getNamespace());
+          assertEquals("Employee", entityType.getBaseType().getName());
+          for (String name : entityType.getNavigationPropertyNames()) {
+            EdmNavigationProperty navProperty = (EdmNavigationProperty) entityType.getProperty(name);          
+            assertEquals(name, navProperty.toString());
+            assertEquals("r_Manager", navProperty.getFromRole());
+            assertEquals("r_Employees", navProperty.getToRole());
+            assertEquals("RefScenario", navProperty.getRelationship().getNamespace());
+            assertEquals(ASSOCIATION, navProperty.getRelationship().getName());
+          }
+        }
+        if ("Employee".equals(entityType.getName())) {
+          for (String name : entityType.getNavigationPropertyNames()) {
+            EdmNavigationProperty navProperty = (EdmNavigationProperty) entityType.getProperty(name);
+            assertEquals(name, navProperty.toString());
+            assertEquals("r_Employees", navProperty.getFromRole());
+            assertEquals("RefScenario", navProperty.getRelationship().getNamespace());
+            assertEquals(ASSOCIATION, navProperty.getRelationship().getName());
+          }
+        }
+      }
+      for (EdmAssociation association : schema.getAssociations()) {
+        EdmMetadataAssociationEnd end;
+        assertEquals(ASSOCIATION, association.getName()); 
+        assertEquals("RefScenario."+association.getName(), association.toString());
+        if ("Employee".equals(association.getEnd1().getEntityType().getName())) {
+          end = (EdmMetadataAssociationEnd) association.getEnd1();
+        } else {
+          end = (EdmMetadataAssociationEnd) association.getEnd2();
+        }  
+        assertEquals("null null", end.toString());
+        assertEquals(EdmMultiplicity.MANY, end.getMultiplicity());
+        assertEquals("r_Employees", end.getRole());
+        assertEquals(EdmAction.Cascade, end.getOnDelete().getAction());
+      }
+    }
+  }
+
+  @Test
+  public void testTwoSchemas() throws XMLStreamException, EntityProviderException,
+  EdmException, UnsupportedEncodingException {
+    int i = 0;
+    String schemasNs[] = { NAMESPACE, NAMESPACE2 };
+    XmlMetadataDeserializer parser = new XmlMetadataDeserializer();
+    InputStream reader = createStreamReader(xmlWithTwoSchemas);
+    EdmDataServices result = parser.readMetadata(reader, true);
+    assertEquals("2.0", result.getDataServiceVersion());
+    assertEquals(2, result.getEdm().getSchemas().size());
+    for (EdmSchema schema : result.getEdm().getSchemas()) {
+      assertEquals(schemasNs[i], schema.getNamespace());
+      assertEquals(1, schema.getEntityTypes().size());
+      i++;
+
+    }
+  }
+
+  @Test
+  public void testProperties() throws EntityProviderException, 
+  XMLStreamException, EdmException, UnsupportedEncodingException {
+    XmlMetadataDeserializer parser = new XmlMetadataDeserializer();
+    InputStream reader = createStreamReader(xmlWithTwoSchemas);
+    EdmDataServices result = parser.readMetadata(reader, true);
+    for (EdmSchema schema : result.getEdm().getSchemas()) {
+      for (EdmEntityType entityType : schema.getEntityTypes()) {
+        if ("Employee".equals(entityType.getName())) {
+          for (String name : entityType.getPropertyNames()) {
+            EdmProperty property = (EdmProperty)(entityType.getProperty(name));
+            if (propertyNames[0].equals(name)) {
+              assertNotNull(property.getFacets());
+              assertEquals(Boolean.FALSE, property.getFacets().isNullable());
+            } else if (propertyNames[1].equals(name)) {
+              assertNull(property.getFacets());
+            }
+          }
+        } else if ("Photo".equals(entityType.getName())) {
+          for (String name : entityType.getPropertyNames()) {
+            EdmProperty sProperty = (EdmProperty) entityType.getProperty(name);
+            if ("Id".equals(sProperty.getName())) {
+              assertEquals(Boolean.FALSE, sProperty.getFacets().isNullable());
+              assertEquals(EdmConcurrencyMode.Fixed, sProperty.getFacets().getConcurrencyMode());
+              assertEquals(new Integer(MAX_LENGTH), sProperty.getFacets().getMaxLength());
+              assertTrue(sProperty.isSimple());
+              assertEquals(EdmSimpleTypeKind.Int32.toString(), sProperty.getType().getName());
+              assertNull(sProperty.getCustomizableFeedMappings());
+            }
+            if ("Name".equals(sProperty.getName())) {
+              assertEquals(Boolean.TRUE, sProperty.getFacets().isUnicode());
+              assertEquals(DEFAULT_VALUE, sProperty.getFacets().getDefaultValue());
+              assertEquals(Boolean.FALSE, sProperty.getFacets().isFixedLength());
+              assertEquals(EdmSimpleTypeKind.String.name(), sProperty.getType().getName());
+              //assertEquals(EdmSimpleTypeKind.String, sProperty.getType());
+              assertNull(sProperty.getCustomizableFeedMappings());
+            }
+            if ("Содержание".equals(sProperty.getName())) {
+              assertEquals(FC_TARGET_PATH, sProperty.getCustomizableFeedMappings().getFcTargetPath());
+              assertEquals(FC_NS_URI, sProperty.getCustomizableFeedMappings().getFcNsUri());
+              assertEquals(FC_NS_PREFIX, sProperty.getCustomizableFeedMappings().getFcNsPrefix());
+              assertEquals(FC_KEEP_IN_CONTENT, sProperty.getCustomizableFeedMappings().isFcKeepInContent());
+              assertEquals(EdmContentKind.text, sProperty.getCustomizableFeedMappings().getFcContentKind());
+            }
+            if ("BinaryData".equals(sProperty.getName())) {
+              assertEquals(MIME_TYPE, sProperty.getMimeType());
+            }
+          }
+        }
+      }
+    }
+  }
+
+  @Test
+  public void testEntitySet() throws XMLStreamException, 
+  EntityProviderException, EdmException, UnsupportedEncodingException {
+    final String xmWithEntityContainer =
+        "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\"" + Edm.NAMESPACE_EDMX_2007_06 + "\">"
+            + "<edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\"" + Edm.NAMESPACE_M_2007_08 + "\">"
+            + "<Schema Namespace=\"" + NAMESPACE + "\" xmlns=\"" + Edm.NAMESPACE_EDM_2008_09 + "\">"
+            + "<EntityType Name= \"Employee\" m:HasStream=\"true\">" + "<Key><PropertyRef Name=\"EmployeeId\"/></Key>"
+            + "<Property Name=\"" + propertyNames[0] + "\" Type=\"Edm.String\" Nullable=\"false\"/>"
+            + "<Property Name=\"" + propertyNames[1] + "\" Type=\"Edm.String\" m:FC_TargetPath=\"SyndicationTitle\"/>"
+            + "</EntityType>" + "<EntityContainer Name=\"Container1\" m:IsDefaultEntityContainer=\"true\">"
+            + "<EntitySet Name=\"Employees\" EntityType=\"RefScenario.Employee\"/>" + "</EntityContainer>"
+            + "</Schema>" + "</edmx:DataServices>" + "</edmx:Edmx>";
+    XmlMetadataDeserializer parser = new XmlMetadataDeserializer();
+    InputStream reader = createStreamReader(xmWithEntityContainer);
+    EdmDataServices result = parser.readMetadata(reader, true);
+    assertEquals("Container1", result.getEdm().getEntityContainer("Container1").getName());
+    for (EdmSchema schema : result.getEdm().getSchemas()) {
+      for (EdmEntityContainer container : schema.getEntityContainers()) {
+        assertEquals("Container1", container.getName());
+        assertEquals(Boolean.TRUE, container.isDefaultEntityContainer());
+        for (EdmEntitySet entitySet : container.getEntitySets()) {
+          assertEquals("Employees", entitySet.getName());
+          assertEquals("Employee", entitySet.getEntityType().getName());
+          assertEquals(NAMESPACE, entitySet.getEntityType().getNamespace());
+        }
+      }
+    }
+  }
+
+  @Test
+  public void testAssociationSet() throws XMLStreamException, 
+  EntityProviderException, EdmException, UnsupportedEncodingException {
+    XmlMetadataDeserializer parser = new XmlMetadataDeserializer();
+    InputStream reader = createStreamReader(xmlWithAssociation);
+    EdmDataServices result = parser.readMetadata(reader, true);
+    for (EdmSchema schema : result.getEdm().getSchemas()) {
+      for (EdmEntityContainer container : schema.getEntityContainers()) {
+        assertEquals(NAMESPACE2, schema.getNamespace());
+        assertEquals("Container1", container.getName());
+        assertEquals(Boolean.TRUE, container.isDefaultEntityContainer());
+        assertNotNull(result.getEdm().getDefaultEntityContainer());
+        assertEquals("Container1", result.getEdm().getDefaultEntityContainer().getName());
+        for (EdmAssociationSet assocSet : container.getAssociationSets()) {
+          assertEquals(ASSOCIATION, assocSet.getName());
+          assertEquals(ASSOCIATION, assocSet.getAssociation().getName());
+          assertEquals(NAMESPACE, assocSet.getAssociation().getNamespace());
+          EdmAssociationSetEnd end;
+          if ("Employees".equals(assocSet.getEnd("r_Employees").getEntitySet().getName())) {
+            end = assocSet.getEnd("r_Employees");
+          } else {
+            end = assocSet.getEnd("r_Manager");
+          }
+          assertEquals("r_Employees", end.getRole());
+        }
+      }
+    }
+  }
+
+ 
+
+  @Test()
+  public void testAlias() throws XMLStreamException, 
+  EntityProviderException, EdmException, UnsupportedEncodingException {
+    final String xml =
+        "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\"" + Edm.NAMESPACE_EDMX_2007_06 + "\">"
+            + "<edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\"" + Edm.NAMESPACE_M_2007_08 + "\">"
+            + "<Schema Namespace=\"" + NAMESPACE + "\" Alias=\"RS\"  xmlns=\"" + Edm.NAMESPACE_EDM_2008_09 + "\">"
+            + "<EntityType Name= \"Employee\">" + "<Key><PropertyRef Name=\"EmployeeId\"/></Key>" + "<Property Name=\""
+            + propertyNames[0] + "\" Type=\"Edm.String\" Nullable=\"false\"/>" + "</EntityType>"
+            + "<EntityType Name=\"Manager\" BaseType=\"RS.Employee\" m:HasStream=\"true\">" + "</EntityType>"
+            + "</Schema>" + "</edmx:DataServices>" + "</edmx:Edmx>";
+    XmlMetadataDeserializer parser = new XmlMetadataDeserializer();
+    InputStream reader = createStreamReader(xml);
+    EdmDataServices result = parser.readMetadata(reader, true);
+    for (EdmSchema schema : result.getEdm().getSchemas()) {
+      assertEquals("RS", schema.getAlias());
+      for (EdmEntityType entityType : schema.getEntityTypes()) {
+        if ("Manager".equals(entityType.getName())) {
+          assertEquals("Employee", entityType.getBaseType().getName());
+          assertEquals("RefScenario", entityType.getBaseType()
+              .getNamespace());
+        }
+      }
+
+    }
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void testEntityTypeWithoutKeys() throws XMLStreamException, 
+  EntityProviderException, EdmException, UnsupportedEncodingException {
+    final String xmlWithoutKeys =
+        "<Schema Namespace=\"" + NAMESPACE + "\" xmlns=\"" + Edm.NAMESPACE_EDM_2008_09 + "\">"
+            + "<EntityType Name= \"Employee\">" + "<Property Name=\"" + propertyNames[0]
+            + "\" Type=\"Edm.String\" Nullable=\"false\"/>" + "</EntityType>" + "</Schema>";
+    XmlMetadataDeserializer parser = new XmlMetadataDeserializer();
+    InputStream reader = createStreamReader(xmlWithoutKeys);
+    parser.readMetadata(reader, true);
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void testInvalidBaseType() throws XMLStreamException, 
+  EntityProviderException, EdmException, UnsupportedEncodingException {
+    final String xmlWithInvalidBaseType =
+        "<Schema Namespace=\"" + NAMESPACE + "\" xmlns=\"" + Edm.NAMESPACE_EDM_2008_09 + "\">"
+            + "<EntityType Name= \"Manager\" BaseType=\"Employee\" m:HasStream=\"true\">" + "</EntityType>"
+            + "</Schema>";
+    XmlMetadataDeserializer parser = new XmlMetadataDeserializer();
+    InputStream reader = createStreamReader(xmlWithInvalidBaseType);
+    parser.readMetadata(reader, true);
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void testInvalidRole() throws XMLStreamException, 
+  EntityProviderException, EdmException, UnsupportedEncodingException {
+    final String xmlWithInvalidAssociation =
+        "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\""
+            + Edm.NAMESPACE_EDMX_2007_06
+            + "\">"
+            + "<edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\""
+            + Edm.NAMESPACE_M_2007_08
+            + "\">"
+            + "<Schema Namespace=\""
+            + NAMESPACE
+            + "\" xmlns=\""
+            + Edm.NAMESPACE_EDM_2008_09
+            + "\">"
+            + "<EntityType Name= \"Employee\">"
+            + "<Key><PropertyRef Name=\"EmployeeId\"/></Key>"
+            + "<Property Name=\""
+            + propertyNames[0]
+            + "\" Type=\"Edm.String\" Nullable=\"false\"/>"
+            + "</EntityType>"
+            + "<EntityType Name=\"Manager\" BaseType=\"RefScenario.Employee\" m:HasStream=\"true\">"
+            + "<NavigationProperty Name=\"nm_Employees\" Relationship=\"RefScenario.ManagerEmployees\" " +
+            "FromRole=\"Manager\" ToRole=\"Employees\" />"
+            + "</EntityType>" + "<Association Name=\"ManagerEmployees\">"
+            + "<End Type=\"RefScenario.Employee\" Multiplicity=\"*\" Role=\"r_Employees\"/>"
+            + "<End Type=\"RefScenario.Manager\" Multiplicity=\"1\" Role=\"r_Manager\"/>" + "</Association>"
+            + "</Schema>"
+            + "</edmx:DataServices>" + "</edmx:Edmx>";
+    XmlMetadataDeserializer parser = new XmlMetadataDeserializer();
+    InputStream reader = createStreamReader(xmlWithInvalidAssociation);
+    parser.readMetadata(reader, true);
+  }
+ 
+  @Test(expected = EntityProviderException.class)
+  public void testInvalidRelationship() throws XMLStreamException, 
+  EntityProviderException, EdmException, UnsupportedEncodingException {
+    final String xmlWithInvalidAssociation =
+        "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\""
+            + Edm.NAMESPACE_EDMX_2007_06
+            + "\">"
+            + "<edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\""
+            + Edm.NAMESPACE_M_2007_08
+            + "\">"
+            + "<Schema Namespace=\""
+            + NAMESPACE
+            + "\" xmlns=\""
+            + Edm.NAMESPACE_EDM_2008_09
+            + "\">"
+            + "<EntityType Name= \"Employee\">"
+            + "<Key><PropertyRef Name=\"EmployeeId\"/></Key>"
+            + "<Property Name=\""
+            + propertyNames[0]
+            + "\" Type=\"Edm.String\" Nullable=\"false\"/>"
+            + "<NavigationProperty Name=\"ne_Manager\" Relationship=\"RefScenario.ManagerEmployee\" " +
+            "FromRole=\"r_Employees\" ToRole=\"r_Manager\" />"
+            + "</EntityType>" + "<EntityType Name=\"Manager\" BaseType=\"RefScenario.Employee\" m:HasStream=\"true\">"
+            + "</EntityType>" + "<Association Name=\"ManagerEmployees\">"
+            + "<End Type=\"RefScenario.Employee\" Multiplicity=\"*\" Role=\"r_Employees\"/>"
+            + "<End Type=\"RefScenario.Manager\" Multiplicity=\"1\" Role=\"r_Manager\"/>" + "</Association>"
+            + "</Schema>"
+            + "</edmx:DataServices>" + "</edmx:Edmx>";
+    XmlMetadataDeserializer parser = new XmlMetadataDeserializer();
+    InputStream reader = createStreamReader(xmlWithInvalidAssociation);
+    parser.readMetadata(reader, true);
+  }
+  @Test(expected = EntityProviderException.class)
+  public void testMissingRelationship() throws Exception {
+    final String xmlWithInvalidAssociation =
+        "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\"" + Edm.NAMESPACE_EDMX_2007_06 + "\">"
+            + "<edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\"" + Edm.NAMESPACE_M_2007_08 + "\">"
+            + "<Schema Namespace=\"" + NAMESPACE + "\" xmlns=\"" + Edm.NAMESPACE_EDM_2008_09 + "\">"
+            + "<EntityType Name= \"Employee\">" + "<Key><PropertyRef Name=\"EmployeeId\"/></Key>" + "<Property Name=\""
+            + propertyNames[0] + "\" Type=\"Edm.String\" Nullable=\"false\"/>"
+            + "<NavigationProperty Name=\"ne_Manager\" />" + "</EntityType>"
+            + "<EntityType Name=\"Manager\" BaseType=\"RefScenario.Employee\" m:HasStream=\"true\">" + "</EntityType>"
+            + "<Association Name=\"ManagerEmployees\">"
+            + "<End Type=\"RefScenario.Employee\" Multiplicity=\"*\" Role=\"r_Employees\"/>"
+            + "<End Type=\"RefScenario.Manager\" Multiplicity=\"1\" Role=\"r_Manager\"/>"
+            + "</Association></Schema></edmx:DataServices></edmx:Edmx>";
+    XmlMetadataDeserializer parser = new XmlMetadataDeserializer();
+    InputStream reader = createStreamReader(xmlWithInvalidAssociation);
+    try {
+      parser.readMetadata(reader, true);
+    } catch (EntityProviderException e) {
+      assertEquals(EntityProviderException.MISSING_ATTRIBUTE.getKey(), e.getMessageReference().getKey());
+      assertEquals(2, e.getMessageReference().getContent().size());
+      assertEquals("Relationship", e.getMessageReference().getContent().get(0));
+      assertEquals("NavigationProperty", e.getMessageReference().getContent().get(1));
+      throw e;
+    }
+  }
+
+  
+  @Test(expected = EntityProviderException.class)
+  public void testMissingEntityType() throws Exception {
+    final String xmlWithInvalidAssociation =
+        "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\""
+            + Edm.NAMESPACE_EDMX_2007_06
+            + "\">"
+            + "<edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\""
+            + Edm.NAMESPACE_M_2007_08
+            + "\">"
+            + "<Schema Namespace=\""
+            + NAMESPACE
+            + "\" xmlns=\""
+            + Edm.NAMESPACE_EDM_2008_09
+            + "\">"
+            + "<EntityType Name= \"Employee\">"
+            + "<Key><PropertyRef Name=\"EmployeeId\"/></Key>"
+            + "<Property Name=\""
+            + propertyNames[0]
+            + "\" Type=\"Edm.String\" Nullable=\"false\"/>"
+            + "<NavigationProperty Name=\"ne_Manager\" Relationship=\"RefScenario.ManagerEmployees\" " +
+            "FromRole=\"r_Employees\" ToRole=\"r_Manager\" />"
+            + "</EntityType>" + "<EntityType Name=\"Manager\" BaseType=\"RefScenario.Employee\" m:HasStream=\"true\">"
+            + "</EntityType>" + "<EntityContainer Name=\"Container1\" m:IsDefaultEntityContainer=\"true\">"
+            + "<EntitySet Name=\"Employees\" />" + "</EntityContainer>" + "<Association Name=\"ManagerEmployees\">"
+            + "<End Type=\"RefScenario.Employee\" Multiplicity=\"*\" Role=\"r_Employees\"/>"
+            + "<End Type=\"RefScenario.Manager\" Multiplicity=\"1\" Role=\"r_Manager\"/>"
+            + "</Association></Schema></edmx:DataServices></edmx:Edmx>";
+    XmlMetadataDeserializer parser = new XmlMetadataDeserializer();
+    InputStream reader = createStreamReader(xmlWithInvalidAssociation);
+    try {
+      parser.readMetadata(reader, true);
+    } catch (EntityProviderException e) {
+      assertEquals(EntityProviderException.MISSING_ATTRIBUTE.getKey(), e.getMessageReference().getKey());
+      assertEquals(2, e.getMessageReference().getContent().size());
+      assertEquals("EntityType", e.getMessageReference().getContent().get(0));
+      assertEquals("EntitySet", e.getMessageReference().getContent().get(1));
+      throw e;
+    }
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void testMissingType() throws Exception {
+    final String xmlWithInvalidAssociation =
+        "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\""
+            + Edm.NAMESPACE_EDMX_2007_06
+            + "\">"
+            + "<edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\""
+            + Edm.NAMESPACE_M_2007_08
+            + "\">"
+            + "<Schema Namespace=\""
+            + NAMESPACE
+            + "\" xmlns=\""
+            + Edm.NAMESPACE_EDM_2008_09
+            + "\">"
+            + "<EntityType Name= \"Employee\">"
+            + "<Key><PropertyRef Name=\"EmployeeId\"/></Key>"
+            + "<Property Name=\""
+            + propertyNames[0]
+            + "\" Nullable=\"false\"/>"
+            + "<NavigationProperty Name=\"ne_Manager\" Relationship=\"RefScenario.ManagerEmployees\" " +
+            "FromRole=\"r_Employees\" ToRole=\"r_Manager\" />"
+            + "</EntityType>" + "<EntityType Name=\"Manager\" BaseType=\"RefScenario.Employee\" m:HasStream=\"true\">"
+            + "</EntityType>" + "<Association Name=\"ManagerEmployees\">"
+            + "<End Type=\"RefScenario.Employee\" Multiplicity=\"*\" Role=\"r_Employees\"/>"
+            + "<End Type=\"RefScenario.Manager\" Multiplicity=\"1\" Role=\"r_Manager\"/>"
+            + "</Association></Schema></edmx:DataServices></edmx:Edmx>";
+    XmlMetadataDeserializer parser = new XmlMetadataDeserializer();
+    InputStream reader = createStreamReader(xmlWithInvalidAssociation);
+    try {
+      parser.readMetadata(reader, true);
+    } catch (EntityProviderException e) {
+      assertEquals(EntityProviderException.MISSING_ATTRIBUTE.getKey(), e.getMessageReference().getKey());
+      assertEquals(2, e.getMessageReference().getContent().size());
+      assertEquals("Type", e.getMessageReference().getContent().get(0));
+      assertEquals("Property", e.getMessageReference().getContent().get(1));
+      throw e;
+    }
+  }
+  @Test(expected = EntityProviderException.class)
+  public void testMissingTypeAtAssociation() throws Exception {
+    final String xmlWithInvalidAssociation =
+        "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\""
+            + Edm.NAMESPACE_EDMX_2007_06
+            + "\">"
+            + "<edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\""
+            + Edm.NAMESPACE_M_2007_08
+            + "\">"
+            + "<Schema Namespace=\""
+            + NAMESPACE
+            + "\" xmlns=\""
+            + Edm.NAMESPACE_EDM_2008_09
+            + "\">"
+            + "<EntityType Name= \"Employee\">"
+            + "<Key><PropertyRef Name=\"EmployeeId\"/></Key>"
+            + "<Property Name=\""
+            + propertyNames[0]
+            + "\" Type=\"Edm.String\" Nullable=\"false\"/>"
+            + "<NavigationProperty Name=\"ne_Manager\" Relationship=\"RefScenario.ManagerEmployees\" " +
+            "FromRole=\"r_Employees\" ToRole=\"r_Manager\" />"
+            + "</EntityType>" + "<EntityType Name=\"Manager\" BaseType=\"RefScenario.Employee\" m:HasStream=\"true\">"
+            + "</EntityType>" + "<Association Name=\"ManagerEmployees\">"
+            + "<End Multiplicity=\"*\" Role=\"r_Employees\"/>"
+            + "<End Type=\"RefScenario.Manager\" Multiplicity=\"1\" Role=\"r_Manager\"/>"
+            + "</Association></Schema></edmx:DataServices></edmx:Edmx>";
+    XmlMetadataDeserializer parser = new XmlMetadataDeserializer();
+    InputStream reader = createStreamReader(xmlWithInvalidAssociation);
+    try {
+      parser.readMetadata(reader, true);
+    } catch (EntityProviderException e) {
+      assertEquals(EntityProviderException.MISSING_ATTRIBUTE.getKey(), e.getMessageReference().getKey());
+      assertEquals(2, e.getMessageReference().getContent().size());
+      assertEquals("Type", e.getMessageReference().getContent().get(0));
+      assertEquals("End", e.getMessageReference().getContent().get(1));
+      throw e;
+    }
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void testMissingTypeAtFunctionImport() throws Exception {
+    final String xml =
+        "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\""
+            + Edm.NAMESPACE_EDMX_2007_06
+            + "\">"
+            + "<edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\""
+            + Edm.NAMESPACE_M_2007_08
+            + "\">"
+            + "<Schema Namespace=\""
+            + NAMESPACE
+            + "\" xmlns=\""
+            + Edm.NAMESPACE_EDM_2008_09
+            + "\">"
+            + "<EntityType Name= \"Employee\" m:HasStream=\"true\">"
+            + "<Key><PropertyRef Name=\"EmployeeId\"/></Key>"
+            + "<Property Name=\""
+            + propertyNames[0]
+            + "\" Type=\"Edm.String\" Nullable=\"false\"/>"
+            + "<Property Name=\""
+            + propertyNames[1]
+            + "\" Type=\"Edm.String\" m:FC_TargetPath=\"SyndicationTitle\"/>"
+            + "</EntityType>"
+            + "<EntityContainer Name=\"Container1\" m:IsDefaultEntityContainer=\"true\">"
+            + "<EntitySet Name=\"Employees\" EntityType=\"RefScenario.Employee\"/>"
+            + "<FunctionImport Name=\"EmployeeSearch\" ReturnType=\"Collection(RefScenario.Employee)\" " +
+            "EntitySet=\"Employees\" m:HttpMethod=\"GET\">"
+            + "<Parameter Name=\"q\" Nullable=\"true\" />" + "</FunctionImport>"
+            + "</EntityContainer></Schema></edmx:DataServices></edmx:Edmx>";
+    XmlMetadataDeserializer parser = new XmlMetadataDeserializer();
+    InputStream reader = createStreamReader(xml);
+    try {
+      parser.readMetadata(reader, true);
+    } catch (EntityProviderException e) {
+      assertEquals(EntityProviderException.MISSING_ATTRIBUTE.getKey(), e.getMessageReference().getKey());
+      assertEquals(2, e.getMessageReference().getContent().size());
+      assertEquals("Type", e.getMessageReference().getContent().get(0));
+      assertEquals("Parameter", e.getMessageReference().getContent().get(1));
+      throw e;
+    }
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void testMissingAssociation() throws Exception {
+    final String xmlWithAssociation =
+        "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\""
+            + Edm.NAMESPACE_EDMX_2007_06
+            + "\">"
+            + "<edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\""
+            + Edm.NAMESPACE_M_2007_08
+            + "\">"
+            + "<Schema Namespace=\""
+            + NAMESPACE
+            + "\" xmlns=\""
+            + Edm.NAMESPACE_EDM_2008_09
+            + "\">"
+            + "<EntityType Name= \"Employee\">"
+            + "<Key><PropertyRef Name=\"EmployeeId\"/></Key>"
+            + "<Property Name=\""
+            + propertyNames[0]
+            + "\" Type=\"Edm.String\" Nullable=\"false\"/>"
+            + "<NavigationProperty Name=\"ne_Manager\" Relationship=\"RefScenario.ManagerEmployees\" " +
+            "FromRole=\"r_Employees\" ToRole=\"r_Manager\" />"
+            + "</EntityType>" + "<EntityContainer Name=\"Container1\" m:IsDefaultEntityContainer=\"true\">"
+            + "<EntitySet Name=\"Employees\" EntityType=\"RefScenario.Employee\"/>" + "<AssociationSet Name=\""
+            + ASSOCIATION
+            // + "\" Association=\"RefScenario." + ASSOCIATION
+            + "\">" + "<End EntitySet=\"Employees\" Role=\"r_Employees\"/>" + "</AssociationSet>"
+            + "</EntityContainer>" + "</Schema>" + "</edmx:DataServices></edmx:Edmx>";
+    XmlMetadataDeserializer parser = new XmlMetadataDeserializer();
+    InputStream reader = createStreamReader(xmlWithAssociation);
+    try {
+      parser.readMetadata(reader, true);
+    } catch (EntityProviderException e) {
+      assertEquals(EntityProviderException.MISSING_ATTRIBUTE.getKey(), e.getMessageReference().getKey());
+      assertEquals(2, e.getMessageReference().getContent().size());
+      assertEquals("Association", e.getMessageReference().getContent().get(0));
+      assertEquals("AssociationSet", e.getMessageReference().getContent().get(1));
+      throw e;
+    }
+  }
+
+  @Test(expected = EdmException.class)
+  public void testInvalidAssociation() throws XMLStreamException, 
+  EntityProviderException, EdmException, UnsupportedEncodingException {
+    final String xmlWithInvalidAssociationSet =
+        "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\""
+            + Edm.NAMESPACE_EDMX_2007_06
+            + "\">"
+            + "<edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\""
+            + Edm.NAMESPACE_M_2007_08
+            + "\">"
+            + "<Schema Namespace=\""
+            + NAMESPACE
+            + "\" xmlns=\""
+            + Edm.NAMESPACE_EDM_2008_09
+            + "\">"
+            + "<EntityType Name= \"Employee\">"
+            + "<Key><PropertyRef Name=\"EmployeeId\"/></Key>"
+            + "<Property Name=\""
+            + propertyNames[0]
+            + "\" Type=\"Edm.String\" Nullable=\"false\"/>"
+            + "<NavigationProperty Name=\"ne_Manager\" Relationship=\"RefScenario.ManagerEmployees\" " +
+            "FromRole=\"r_Employees\" ToRole=\"r_Manager\" />"
+            + "</EntityType>"
+            + "<EntityType Name=\"Manager\" BaseType=\"RefScenario.Employee\" m:HasStream=\"true\">"
+            + "<NavigationProperty Name=\"nm_Employees\" Relationship=\"RefScenario.ManagerEmployees\" " +
+            "FromRole=\"r_Manager\" ToRole=\"r_Employees\" />"
+            + "</EntityType>" + "<Association Name=\"" + ASSOCIATION + "\">"
+            + "<End Type=\"RefScenario.Employee\" Multiplicity=\"*\" Role=\"r_Employees\">"
+            + "<OnDelete Action=\"Cascade\"/>" + "</End>"
+            + "<End Type=\"RefScenario.Manager\" Multiplicity=\"1\" Role=\"r_Manager\"/>" + "</Association>"
+            + "<EntityContainer Name=\"Container1\" m:IsDefaultEntityContainer=\"true\">"
+            + "<EntitySet Name=\"Employees\" EntityType=\"RefScenario.Employee\"/>"
+            + "<EntitySet Name=\"Managers\" EntityType=\"RefScenario.Manager\"/>" + "<AssociationSet Name=\""
+            + ASSOCIATION + "\" Association=\"RefScenario2." + ASSOCIATION + "\">"
+            + "<End EntitySet=\"Managers\" Role=\"r_Manager\"/>"
+            + "<End EntitySet=\"Employees\" Role=\"r_Employees\"/>" + "</AssociationSet>" + "</EntityContainer>"
+            + "</Schema>" + "</edmx:DataServices>" + "</edmx:Edmx>";
+    XmlMetadataDeserializer parser = new XmlMetadataDeserializer();
+    InputStream reader = createStreamReader(xmlWithInvalidAssociationSet);
+    parser.readMetadata(reader, true);
+
+  }
+
+  @Test(expected = EdmException.class)
+  public void testInvalidAssociationEnd() throws XMLStreamException, 
+  EntityProviderException, EdmException, UnsupportedEncodingException {
+    final String employees = "r_Employees";
+    final String manager = "r_Manager";
+    final String xmlWithInvalidAssociationSetEnd =
+        "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\"" + Edm.NAMESPACE_EDMX_2007_06 + "\">"
+            + "<edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\"" + Edm.NAMESPACE_M_2007_08 + "\">"
+            + "<Schema Namespace=\"" + NAMESPACE + "\" xmlns=\"" + Edm.NAMESPACE_EDM_2008_09 + "\">"
+            + "<EntityType Name= \"Employee\">" + "<Key><PropertyRef Name=\"EmployeeId\"/></Key>" + "<Property Name=\""
+            + propertyNames[0] + "\" Type=\"Edm.String\" Nullable=\"false\"/>"
+            + "<NavigationProperty Name=\"ne_Manager\" Relationship=\"RefScenario.ManagerEmployees\" FromRole=\""
+            + employees + "\" ToRole=\"" + manager + "\" />" + "</EntityType>"
+            + "<EntityType Name=\"Manager\" BaseType=\"RefScenario.Employee\" m:HasStream=\"true\">"
+            + "<NavigationProperty Name=\"nm_Employees\" Relationship=\"RefScenario.ManagerEmployees\" FromRole=\""
+            + manager + "\" ToRole=\"" + employees + "\" />" + "</EntityType>" + "<Association Name=\"" + ASSOCIATION
+            + "\">"
+            + "<End Type=\"RefScenario.Employee\" Multiplicity=\"*\" Role=\"" + employees + "1" + "\"/>"
+            + "<End Type=\"RefScenario.Manager\" Multiplicity=\"1\" Role=\"" + manager + "\"/>" + "</Association>"
+            + "<EntityContainer Name=\"Container1\" m:IsDefaultEntityContainer=\"true\">"
+            + "<EntitySet Name=\"Employees\" EntityType=\"RefScenario.Employee\"/>"
+            + "<EntitySet Name=\"Managers\" EntityType=\"RefScenario.Manager\"/>" + "<AssociationSet Name=\""
+            + ASSOCIATION + "\" Association=\"RefScenario2." + ASSOCIATION + "\">"
+            + "<End EntitySet=\"Managers\" Role=\"" + manager + "\"/>" + "<End EntitySet=\"Employees\" Role=\""
+            + employees + "\"/>" + "</AssociationSet>" + "</EntityContainer>" + "</Schema>" + "</edmx:DataServices>"
+            + "</edmx:Edmx>";
+    XmlMetadataDeserializer parser = new XmlMetadataDeserializer();
+    InputStream reader = createStreamReader(xmlWithInvalidAssociationSetEnd);
+    parser.readMetadata(reader, true);
+
+  }
+
+  @Test(expected = EdmException.class)
+  public void testInvalidAssociationEnd2() throws XMLStreamException, 
+  EntityProviderException, EdmException, UnsupportedEncodingException {
+    final String employees = "r_Employees";
+    final String manager = "r_Manager";
+    final String xmlWithInvalidAssociationSetEnd =
+        "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\"" + Edm.NAMESPACE_EDMX_2007_06 + "\">"
+            + "<edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\"" + Edm.NAMESPACE_M_2007_08 + "\">"
+            + "<Schema Namespace=\"" + NAMESPACE + "\" xmlns=\"" + Edm.NAMESPACE_EDM_2008_09 + "\">"
+            + "<EntityType Name= \"Employee\">" + "<Key><PropertyRef Name=\"EmployeeId\"/></Key>" + "<Property Name=\""
+            + propertyNames[0] + "\" Type=\"Edm.String\" Nullable=\"false\"/>"
+            + "<NavigationProperty Name=\"ne_Manager\" Relationship=\"RefScenario.ManagerEmployees\" FromRole=\""
+            + employees + "\" ToRole=\"" + manager + "\" />" + "</EntityType>"
+            + "<EntityType Name=\"Manager\" BaseType=\"RefScenario.Employee\" m:HasStream=\"true\">"
+            + "<NavigationProperty Name=\"nm_Employees\" Relationship=\"RefScenario.ManagerEmployees\" FromRole=\""
+            + manager + "\" ToRole=\"" + employees + "\" />" + "</EntityType>" + "<Association Name=\"" + ASSOCIATION
+            + "\">"
+            + "<End Type=\"RefScenario.Employee\" Multiplicity=\"*\" Role=\"" + employees + "\"/>"
+            + "<End Type=\"RefScenario.Manager\" Multiplicity=\"1\" Role=\"" + manager + "\"/>" + "</Association>"
+            + "<EntityContainer Name=\"Container1\" m:IsDefaultEntityContainer=\"true\">"
+            + "<EntitySet Name=\"Employees\" EntityType=\"RefScenario.Employee\"/>"
+            + "<EntitySet Name=\"Managers\" EntityType=\"RefScenario.Manager\"/>" + "<AssociationSet Name=\""
+            + ASSOCIATION + "\" Association=\"RefScenario2." + ASSOCIATION + "\">"
+            + "<End EntitySet=\"Managers\" Role=\"" + manager + "\"/>" + "<End EntitySet=\"Managers\" Role=\""
+            + manager + "\"/>" + "</AssociationSet>" + "</EntityContainer>" + "</Schema>" + "</edmx:DataServices>"
+            + "</edmx:Edmx>";
+    XmlMetadataDeserializer parser = new XmlMetadataDeserializer();
+    InputStream reader = createStreamReader(xmlWithInvalidAssociationSetEnd);
+    parser.readMetadata(reader, true);
+
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void testInvalidEntitySet() throws XMLStreamException, 
+  EntityProviderException, EdmException, UnsupportedEncodingException {
+    final String xmWithEntityContainer =
+        "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\"" + Edm.NAMESPACE_EDMX_2007_06 + "\">"
+            + "<edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\"" + Edm.NAMESPACE_M_2007_08 + "\">"
+            + "<Schema Namespace=\"" + NAMESPACE + "\" xmlns=\"" + Edm.NAMESPACE_EDM_2008_09 + "\">"
+            + "<EntityType Name= \"Employee\" m:HasStream=\"true\">" + "<Key><PropertyRef Name=\"EmployeeId\"/></Key>"
+            + "<Property Name=\"" + propertyNames[0] + "\" Type=\"Edm.String\" Nullable=\"false\"/>"
+            + "<Property Name=\"" + propertyNames[1] + "\" Type=\"Edm.String\" m:FC_TargetPath=\"SyndicationTitle\"/>"
+            + "</EntityType>" + "<EntityContainer Name=\"Container1\" m:IsDefaultEntityContainer=\"true\">"
+            + "<EntitySet Name=\"Employees\" EntityType=\"RefScenario.Mitarbeiter\"/>" + "</EntityContainer>"
+            + "</Schema>" + "</edmx:DataServices>" + "</edmx:Edmx>";
+    XmlMetadataDeserializer parser = new XmlMetadataDeserializer();
+    InputStream reader = createStreamReader(xmWithEntityContainer);
+    parser.readMetadata(reader, true);
+
+  }
+
+  @Test
+  public void testEntityTypeInOtherSchema() throws XMLStreamException, 
+  EntityProviderException, EdmException, UnsupportedEncodingException {
+    final String xmWithEntityContainer =
+        "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\"" + Edm.NAMESPACE_EDMX_2007_06 + "\">"
+            + "<edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\"" + Edm.NAMESPACE_M_2007_08 + "\">"
+            + "<Schema Namespace=\"" + NAMESPACE + "\" xmlns=\"" + Edm.NAMESPACE_EDM_2008_09 + "\">"
+            + "<EntityType Name= \"Employee\" m:HasStream=\"true\">" + "<Key><PropertyRef Name=\"EmployeeId\"/></Key>"
+            + "<Property Name=\"" + propertyNames[0] + "\" Type=\"Edm.String\" Nullable=\"false\"/>" + "</EntityType>"
+            + "<EntityContainer Name=\"Container1\" m:IsDefaultEntityContainer=\"true\">"
+            + "<EntitySet Name=\"Photos\" EntityType=\"" + NAMESPACE2 + ".Photo\"/>" + "</EntityContainer>"
+            + "</Schema>" + "<Schema Namespace=\"" + NAMESPACE2 + "\" xmlns=\"" + Edm.NAMESPACE_EDM_2008_09 + "\">"
+            + "<EntityType Name= \"Photo\">" + "<Key><PropertyRef Name=\"Id\"/></Key>"
+            + "<Property Name=\"Id\" Type=\"Edm.Int32\" Nullable=\"false\"/>" + "</EntityType>" + "</Schema>"
+            + "</edmx:DataServices>"
+            + "</edmx:Edmx>";
+    XmlMetadataDeserializer parser = new XmlMetadataDeserializer();
+    InputStream reader = createStreamReader(xmWithEntityContainer);
+    EdmDataServices result = parser.readMetadata(reader, true);
+    assertEquals("2.0", result.getDataServiceVersion());
+    for (EdmSchema schema : result.getEdm().getSchemas()) {
+      for (EdmEntityContainer container : schema.getEntityContainers()) {
+        assertEquals("Container1", container.getName());
+        for (EdmEntitySet entitySet : container.getEntitySets()) {
+          assertEquals(NAMESPACE2, entitySet.getEntityType().getNamespace());
+          assertEquals("Photo", entitySet.getEntityType().getName());
+        }
+      }
+    }
+  }
+
+  @Test
+  public void testMultipleSchemas() throws XMLStreamException, 
+  EntityProviderException, EdmException, UnsupportedEncodingException {
+    final String xmWithEntityContainer =
+        "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\"" + Edm.NAMESPACE_EDMX_2007_06 + "\">"
+            + "<edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\"" + Edm.NAMESPACE_M_2007_08 + "\">"
+            + "<Schema Namespace=\"" + NAMESPACE + "\" xmlns=\"" + Edm.NAMESPACE_EDM_2008_09 + "\">"
+            + "<EntityType Name= \"Employee\" m:HasStream=\"true\">" + "<Key><PropertyRef Name=\"EmployeeId\"/></Key>"
+            + "<Property Name=\"" + propertyNames[0] + "\" Type=\"Edm.String\" Nullable=\"false\"/>" + "</EntityType>"
+            + "<EntityContainer Name=\"Container1\" m:IsDefaultEntityContainer=\"true\">"
+            + "<EntitySet Name=\"Photos\" EntityType=\"" + NAMESPACE2 + ".Photo\"/>" + "</EntityContainer>"
+            + "<EntityContainer Name=\"Container2\" m:IsDefaultEntityContainer=\"true\">"
+            + "<EntitySet Name=\"Sign\" EntityType=\"" + NAMESPACE3 + ".Sign\"/>" + "</EntityContainer>"
+            + "</Schema>"
+
+            + "<Schema Namespace=\"" + NAMESPACE2 + "\" xmlns=\"" + Edm.NAMESPACE_EDM_2008_09 + "\">"
+            + "<EntityType Name= \"Photo\">" + "<Key><PropertyRef Name=\"Id\"/></Key>"
+            + "<Property Name=\"Id\" Type=\"Edm.Int32\" Nullable=\"false\"/>" + "</EntityType>"
+            + "<EntityType Name= \"Name\">" + "<Key><PropertyRef Name=\"NameId\"/></Key>"
+            + "<Property Name=\"NameId\" Type=\"Edm.Int32\" Nullable=\"false\"/>" + "</EntityType>"
+            + "<EntityContainer Name=\"Container2\" m:IsDefaultEntityContainer=\"true\">"
+            + "<EntitySet Name=\"Name\" EntityType=\"" + NAMESPACE2 + ".Name\"/>"
+            + "<EntitySet Name=\"Photo\" EntityType=\"" + NAMESPACE2 + ".Photo\"/>"
+            + "</EntityContainer>"
+            + "</Schema>"
+
+            + "<Schema Namespace=\"" + NAMESPACE3 + "\" xmlns=\"" + Edm.NAMESPACE_EDM_2008_09 + "\">"
+            + "<EntityType Name= \"Sign\">" + "<Key><PropertyRef Name=\"Id\"/></Key>"
+      

<TRUNCATED>

[22/24] olingo-odata2 git commit: [OLINGO-1253]Client Module for Olingo v2

Posted by ar...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmFunctionImportParameter.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmFunctionImportParameter.java b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmFunctionImportParameter.java
new file mode 100644
index 0000000..7a0ca1f
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmFunctionImportParameter.java
@@ -0,0 +1,140 @@
+/*******************************************************************************
+ * 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.client.core.edm.Impl;
+
+import org.apache.olingo.odata2.api.edm.EdmAnnotations;
+import org.apache.olingo.odata2.api.edm.EdmFacets;
+import org.apache.olingo.odata2.api.edm.EdmMapping;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeKind;
+import org.apache.olingo.odata2.client.api.edm.EdmDocumentation;
+
+/**
+ * Objects of this class represent function import parameters
+ * 
+ */
+public class EdmFunctionImportParameter {
+
+  private String name;
+  private String mode;
+  private EdmSimpleTypeKind type;
+  private EdmFacets facets;
+  private EdmMapping mapping;
+  private EdmDocumentation documentation;
+  private EdmAnnotations annotations;
+
+  /**
+   * @return <b>String</b> name of the parameter
+   */
+  public String getName() {
+    return name;
+  }
+
+  /**
+   * @return {@link EdmSimpleTypeKind} of this parameter
+   */
+  public EdmSimpleTypeKind getType() {
+    return type;
+  }
+
+  /**
+   * @return {@link EdmFacets} of this parameter
+   */
+  public EdmFacets getFacets() {
+    return facets;
+  }
+
+  /**
+   * @return {@link EdmMappingImpl} of this parameter
+   */
+  public EdmMapping getMapping() {
+    return mapping;
+  }
+
+  /**
+   * Sets the name of this {@link EdmFunctionImportParameter}
+   * @param name
+   * @return {@link EdmFunctionImportParameter} for method chaining
+   */
+  public EdmFunctionImportParameter setName(final String name) {
+    this.name = name;
+    return this;
+  }
+
+  /**
+   * Sets the mode of this {@link EdmFunctionImportParameter}
+   * @param mode
+   * @return {@link EdmFunctionImportParameter} for method chaining
+   */
+  public EdmFunctionImportParameter setMode(final String mode) {
+    this.mode = mode;
+    return this;
+  }
+
+  /**
+   * Sets the {@link EdmSimpleTypeKind} of this {@link EdmFunctionImportParameter}
+   * @param type
+   * @return {@link EdmFunctionImportParameter} for method chaining
+   */
+  public EdmFunctionImportParameter setType(final EdmSimpleTypeKind type) {
+    this.type = type;
+    return this;
+  }
+
+  /**
+   * Sets the {@link EdmFacets} of this {@link EdmFunctionImportParameter}
+   * @param facets
+   * @return {@link EdmFunctionImportParameter} for method chaining
+   */
+  public EdmFunctionImportParameter setFacets(final EdmFacets facets) {
+    this.facets = facets;
+    return this;
+  }
+
+  /**
+   * Sets the {@link EdmMappingImpl} of this {@link EdmFunctionImportParameter}
+   * @param mapping
+   * @return {@link EdmFunctionImportParameter} for method chaining
+   */
+  public EdmFunctionImportParameter setMapping(final EdmMapping mapping) {
+    this.mapping = mapping;
+    return this;
+  }
+
+  /**
+   * Sets the {@link Documentation} of this {@link EdmFunctionImportParameter}
+   * @param documentation
+   * @return {@link EdmFunctionImportParameter} for method chaining
+   */
+  public EdmFunctionImportParameter setDocumentation(final EdmDocumentation documentation) {
+    this.documentation = documentation;
+    return this;
+  }
+
+  public void setAnnotations(EdmAnnotationsImpl annotations) {
+    this.annotations = annotations;
+  }
+  
+  public EdmAnnotations getAnnotations() {
+    return this.annotations;
+  }  
+  @Override
+  public String toString() {
+      return String.format(name);
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmImpl.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmImpl.java b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmImpl.java
new file mode 100644
index 0000000..3933cb0
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmImpl.java
@@ -0,0 +1,207 @@
+/*******************************************************************************
+ * 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.client.core.edm.Impl;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.apache.olingo.odata2.api.edm.EdmAssociation;
+import org.apache.olingo.odata2.api.edm.EdmComplexType;
+import org.apache.olingo.odata2.api.edm.EdmEntityContainer;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmEntityType;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmFunctionImport;
+import org.apache.olingo.odata2.api.edm.EdmServiceMetadata;
+import org.apache.olingo.odata2.api.edm.FullQualifiedName;
+import org.apache.olingo.odata2.client.api.edm.ClientEdm;
+import org.apache.olingo.odata2.client.api.edm.EdmSchema;
+
+/**
+ * Objects of this class represent Edm
+ */
+public class EdmImpl implements ClientEdm {
+
+  protected Map<FullQualifiedName, EdmEntityContainer> edmEntityContainers;
+  protected Map<FullQualifiedName, EdmEntityType> edmEntityTypes;
+  private Map<FullQualifiedName, EdmComplexType> edmComplexTypes;
+  private Map<FullQualifiedName, EdmAssociation> edmAssociations;
+  private Map<String, String> aliasToNamespaceInfo;
+  private List<EdmEntitySet> edmEntitySets;
+  private List<EdmFunctionImport> edmFunctionImports;
+  private List<EdmSchema> edmSchema;
+  private EdmEntityContainer defaultEdmEntityContainer;
+
+  public EdmImpl() {
+    edmEntityContainers = new HashMap<FullQualifiedName, EdmEntityContainer>();
+    edmEntityTypes = new HashMap<FullQualifiedName, EdmEntityType>();
+    edmComplexTypes = new HashMap<FullQualifiedName, EdmComplexType>();
+    edmAssociations = new HashMap<FullQualifiedName, EdmAssociation>();
+    aliasToNamespaceInfo = new HashMap<String, String>();
+  }
+
+  @Override
+  public EdmEntityContainer getEntityContainer(final String name)
+      throws EdmException {
+    for (Entry<FullQualifiedName, EdmEntityContainer> entry : edmEntityContainers.entrySet()) {
+      if (entry.getKey().getName().equals(name)) {
+        return entry.getValue();
+      }
+    }
+    return null;
+  }
+
+  public EdmImpl setEdmSchemas(List<EdmSchema> edmSchema) {
+    this.edmSchema = edmSchema;
+    return this;
+  }
+
+  @Override
+  public EdmEntityType getEntityType(final String namespaceOrAlias,
+      final String name) throws EdmException {
+    FullQualifiedName fqName = getNamespaceForAlias(namespaceOrAlias, name);
+    return edmEntityTypes.get(fqName);
+  }
+
+  private FullQualifiedName getNamespaceForAlias(final String namespaceOrAlias, String name)
+      throws EdmException {
+    String namespace = aliasToNamespaceInfo.get(namespaceOrAlias);
+    if (namespace != null) {
+      //Namespace to alias mapping found
+      return new FullQualifiedName(namespace, name);
+    } else {
+      //No mapping found. Parameter must be the namespace
+      return new FullQualifiedName(namespaceOrAlias, name);
+    }
+  }
+
+  @Override
+  public EdmComplexType getComplexType(final String namespaceOrAlias,
+      final String name) throws EdmException {
+    FullQualifiedName fqName = getNamespaceForAlias(namespaceOrAlias, name);
+    return edmComplexTypes.get(fqName);
+  }
+
+  @Override
+  public EdmAssociation getAssociation(final String namespaceOrAlias,
+      final String name) throws EdmException {
+    FullQualifiedName fqName = getNamespaceForAlias(namespaceOrAlias, name);
+    return edmAssociations.get(fqName);
+  }
+
+  public EdmImpl setDefaultEntityContainer(EdmEntityContainer defaultEdmEntityContainer) throws EdmException {
+    this.defaultEdmEntityContainer = defaultEdmEntityContainer;
+    return this;
+  }
+
+  @Override
+  public EdmEntityContainer getDefaultEntityContainer() throws EdmException {
+    return defaultEdmEntityContainer;
+  }
+
+  @Override
+  public List<EdmEntitySet> getEntitySets() throws EdmException {
+    return edmEntitySets;
+  }
+
+  @Override
+  public List<EdmFunctionImport> getFunctionImports() throws EdmException {
+    return edmFunctionImports;
+  }
+
+  @Override
+  public EdmServiceMetadata getServiceMetadata() {
+    return null;
+  }
+
+  public Map<FullQualifiedName, EdmEntityContainer> getEdmEntityContainers() {
+    return edmEntityContainers;
+  }
+
+  public EdmImpl setEdmEntityContainers(Map<FullQualifiedName, EdmEntityContainer> edmEntityContainers) {
+    this.edmEntityContainers = edmEntityContainers;
+    return this;
+  }
+
+  public Map<FullQualifiedName, EdmEntityType> getEdmEntityTypes() {
+    return edmEntityTypes;
+  }
+
+  public EdmImpl setEdmEntityTypes(Map<FullQualifiedName, EdmEntityType> edmEntityTypes) {
+    this.edmEntityTypes = edmEntityTypes;
+    return this;
+  }
+
+  public Map<FullQualifiedName, EdmComplexType> getEdmComplexTypes() {
+    return edmComplexTypes;
+  }
+
+  public EdmImpl setEdmComplexTypes(Map<FullQualifiedName, EdmComplexType> edmComplexTypes) {
+    this.edmComplexTypes = edmComplexTypes;
+    return this;
+  }
+
+  public Map<FullQualifiedName, EdmAssociation> getEdmAssociations() {
+    return edmAssociations;
+  }
+
+  public EdmImpl setEdmAssociations(Map<FullQualifiedName, EdmAssociation> edmAssociations) {
+    this.edmAssociations = edmAssociations;
+    return this;
+  }
+
+  public Map<String, String> getAliasToNamespaceInfo() {
+    return aliasToNamespaceInfo;
+  }
+
+  public EdmImpl setAliasToNamespaceInfo(Map<String, String> aliasToNamespaceInfo) {
+    this.aliasToNamespaceInfo = aliasToNamespaceInfo;
+    return this;
+  }
+
+  public List<EdmEntitySet> getEdmEntitySets() {
+    return edmEntitySets;
+  }
+
+  public EdmImpl setEdmEntitySets(List<EdmEntitySet> edmEntitySets) {
+    this.edmEntitySets = edmEntitySets;
+    return this;
+  }
+
+  public List<EdmFunctionImport> getEdmFunctionImports() {
+    return edmFunctionImports;
+  }
+
+  public EdmImpl setEdmFunctionImports(List<EdmFunctionImport> edmFunctionImports) {
+    this.edmFunctionImports = edmFunctionImports;
+    return this;
+  }
+
+  @Override
+  public List<EdmSchema> getSchemas() {
+    return edmSchema;
+  }
+
+  @Override
+  public String toString() {
+    return String.format("EdmImpl");
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmKeyImpl.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmKeyImpl.java b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmKeyImpl.java
new file mode 100644
index 0000000..6a3ad4b
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmKeyImpl.java
@@ -0,0 +1,101 @@
+/*******************************************************************************
+ * 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.client.core.edm.Impl;
+
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.EdmAnnotationAttribute;
+import org.apache.olingo.odata2.api.edm.EdmAnnotationElement;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+
+/**
+ * Objects of this class represent a key for an entity type
+ * 
+ */
+public class EdmKeyImpl {
+
+  private List<EdmProperty> keys;
+  private List<EdmAnnotationAttribute> annotationAttributes;
+  private List<EdmAnnotationElement> annotationElements;
+
+  /**
+   * @return List<{@link PropertyRef}> references to the key properties
+   */
+  public List<EdmProperty> getKeys() {
+    return keys;
+  }
+
+  /**
+   * @return List of {@link AnnotationAttribute} annotation attributes
+   */
+  public List<EdmAnnotationAttribute> getAnnotationAttributes() {
+    return annotationAttributes;
+  }
+
+  /**
+   * @return List of {@link AnnotationElement} annotation elements
+   */
+  public List<EdmAnnotationElement> getAnnotationElements() {
+    return annotationElements;
+  }
+
+  /**
+   * Sets the {@link Property}s by their {@link PropertyRef} for this {@link EdmKeyImpl}
+   * @param keys
+   * @return {@link EdmKeyImpl} for method chaining
+   */
+  public EdmKeyImpl setKeys(final List<EdmProperty> keys) {
+    this.keys = keys;
+    return this;
+  }
+
+  /**
+   * Sets the List of {@link AnnotationAttribute} for this {@link EdmKeyImpl}
+   * @param annotationAttributes
+   * @return {@link EdmKeyImpl} for method chaining
+   */
+  public EdmKeyImpl setAnnotationAttributes(final List<EdmAnnotationAttribute> annotationAttributes) {
+    this.annotationAttributes = annotationAttributes;
+    return this;
+  }
+
+  /**
+   * Sets the List of {@link AnnotationElement} for this {@link EdmKeyImpl}
+   * @param annotationElements
+   * @return {@link EdmKeyImpl} for method chaining
+   */
+  public EdmKeyImpl setAnnotationElements(final List<EdmAnnotationElement> annotationElements) {
+    this.annotationElements = annotationElements;
+    return this;
+  }
+  @Override
+  public String toString() {
+    StringBuffer keyValues = new StringBuffer();
+    for(EdmProperty key:keys){
+      try {
+        keyValues.append(key.getName().toString());
+      } catch (EdmException e) {
+        keyValues.append("null");
+      }
+      keyValues.append(",");
+    }
+    return String.format((keyValues.substring(0, keyValues.length()-1)).toString());
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmMappingImpl.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmMappingImpl.java b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmMappingImpl.java
new file mode 100644
index 0000000..6d09bb6
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmMappingImpl.java
@@ -0,0 +1,99 @@
+/*******************************************************************************
+ * 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.client.core.edm.Impl;
+
+import org.apache.olingo.odata2.api.edm.EdmMapping;
+
+/**
+ * Object of this class represent the mapping of a value to a MIME type.
+ * 
+ */
+public class EdmMappingImpl implements EdmMapping {
+
+  private String value;
+  private Object object;
+  private String mediaResourceSourceKey;
+  private String mediaResourceMimeTypeKey;
+
+  @Override
+  public String getInternalName() {
+    return value;
+  }
+
+  @Override
+  public Object getObject() {
+    return object;
+  }
+
+  @Override
+  public String getMediaResourceSourceKey() {
+    return mediaResourceSourceKey;
+  }
+
+  @Override
+  public String getMediaResourceMimeTypeKey() {
+    return mediaResourceMimeTypeKey;
+  }
+
+  /**
+   * Sets the value for this {@link EdmMappingImpl}.
+   * @param value
+   * @return {@link EdmMappingImpl} for method chaining
+   */
+  public EdmMappingImpl setInternalName(final String value) {
+    this.value = value;
+    return this;
+  }
+
+  /**
+   * Sets an object. This method can be used by a provider to set whatever it wants to associate with this.
+   * @param object
+   * @return {@link EdmMappingImpl} for method chaining
+   */
+  public EdmMappingImpl setObject(final Object object) {
+    this.object = object;
+    return this;
+  }
+
+  /**
+   * Sets the key for the resource source key which is used for the lookup in the data map
+   * @param mediaResourceSourceKey under which the source can be found in the data map
+   * @return {@link EdmMappingImpl} for method chaining
+   */
+  public EdmMappingImpl setMediaResourceSourceKey(final String mediaResourceSourceKey) {
+    this.mediaResourceSourceKey = mediaResourceSourceKey;
+    return this;
+  }
+
+  /**
+   * Sets the key for the resource mime type key which is used for the lookup in the data map
+   * @param mediaResourceMimeTypeKey under which the mime type can be found in the data map
+   * @return {@link EdmMappingImpl} for method chaining
+   */
+  public EdmMappingImpl setMediaResourceMimeTypeKey(final String mediaResourceMimeTypeKey) {
+    this.mediaResourceMimeTypeKey = mediaResourceMimeTypeKey;
+    return this;
+  }
+  
+  @Override
+  public String toString() {
+      return String.format(value);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmNamedImpl.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmNamedImpl.java b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmNamedImpl.java
new file mode 100644
index 0000000..6d9411c
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmNamedImpl.java
@@ -0,0 +1,82 @@
+/*******************************************************************************
+ * 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.client.core.edm.Impl;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmNamed;
+
+/**
+ * See in ABNF
+ * <p>
+ * <code>
+ *   Note:this pattern is overly restrictive, the normative definition is type TSimpleIdentifier in OData EDM XML Schema
+ *   <br/>
+ *   odataIdentifier             = identifierLeadingCharacter *127identifierCharacter
+ *   <br/>
+ *   identifierLeadingCharacter  = ALPHA / "_"         ; plus Unicode characters from the categories L or Nl
+ *   <br/>
+ *   identifierCharacter         = ALPHA / "_" / DIGIT ; plus Unicode characters from the categories L, Nl, Nd, Mn,
+ *   Mc, Pc, or Cf
+ *   <br/>
+ * </code>
+ * </p>
+ * And in OData V2 MC-CSDL (Release v20110610)
+ * <p>
+ * Section 2.2.6 SimpleIdentifier<br/>
+ * SimpleIdentifier is a string-based representation. The maximum length of the identifier MUST be less than 480.
+ * The below pattern represents the allowed identifiers in ECMA specification:
+ * Pattern: <code>value="[\p{L}\p{Nl}][\p{L}\p{Nl}\p{Nd}\p{Mn}\p{Mc}\p{Pc}\p{Cf}]{0,}"</code>
+ * </p>
+ *
+ */
+public abstract class EdmNamedImpl implements EdmNamed {
+  
+  private static final Pattern PATTERN_VALID_NAME = Pattern.compile(
+      "\\A[_\\p{L}\\p{Nl}][_\\p{L}\\p{Nl}\\p{Nd}\\p{Mn}\\p{Mc}\\p{Pc}\\p{Cf}]{0,}\\Z");
+ 
+  protected EdmImpl edm;
+  protected String name;
+
+  public void setEdm(EdmImpl edm) {
+    this.edm = edm;
+  }
+
+  public void setName(String name) throws EdmException  {
+    this.name = getValidatedName(name);
+  }
+
+  @Override
+  public String getName() throws EdmException {
+    return name;
+  }
+  private String getValidatedName(final String name) throws EdmException {
+    Matcher matcher = PATTERN_VALID_NAME.matcher(name);
+    if (matcher.matches()) {
+      return name;
+    }
+    throw new EdmException(EdmException.NAMINGERROR.addContent(name));
+  }
+  @Override
+  public String toString() {
+      return String.format(name);
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmNavigationPropertyImpl.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmNavigationPropertyImpl.java b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmNavigationPropertyImpl.java
new file mode 100644
index 0000000..11aa7e9
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmNavigationPropertyImpl.java
@@ -0,0 +1,119 @@
+/*******************************************************************************
+ * 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.client.core.edm.Impl;
+
+import org.apache.olingo.odata2.api.edm.EdmAnnotatable;
+import org.apache.olingo.odata2.api.edm.EdmAnnotations;
+import org.apache.olingo.odata2.api.edm.EdmAssociation;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmMapping;
+import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
+import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
+import org.apache.olingo.odata2.api.edm.EdmType;
+import org.apache.olingo.odata2.api.edm.FullQualifiedName;
+import org.apache.olingo.odata2.api.edm.provider.Mapping;
+import org.apache.olingo.odata2.client.api.edm.EdmDocumentation;
+
+/**
+ * Objects of this class represent EdmNavigationProperty
+ *
+ */
+public class EdmNavigationPropertyImpl extends EdmTypedImpl implements EdmNavigationProperty, EdmAnnotatable {
+
+  private EdmAnnotations annotations;
+  private FullQualifiedName relationship;
+  private String fromRole;
+  private String toRole;
+  private EdmDocumentation documentation;
+  private Mapping mapping;
+
+  public EdmDocumentation getDocumentation() {
+    return documentation;
+  }
+
+  public void setDocumentation(EdmDocumentation documentation) {
+    this.documentation = documentation;
+  }
+
+  public void setMapping(Mapping mapping) {
+    this.mapping = mapping;
+  }
+
+
+  public void setAnnotations(EdmAnnotations annotations) {
+    this.annotations = annotations;
+  }
+
+  public void setFromRole(String fromRole) {
+    this.fromRole = fromRole;
+  }
+
+  public void setToRole(String toRole) {
+    this.toRole = toRole;
+  }
+
+  @Override
+  public EdmType getType() throws EdmException {
+    return edmType;
+  }
+
+  @Override
+  public EdmMultiplicity getMultiplicity() throws EdmException {
+    return multiplicity;
+  }
+
+  @Override
+  public EdmAssociation getRelationship() throws EdmException {
+    return edm.getAssociation(relationship.getNamespace(), relationship.getName());
+  }
+  
+  public FullQualifiedName getRelationshipName() throws EdmException {
+    return relationship;
+  }
+  
+  public void setRelationshipName( FullQualifiedName relationship){
+    this.relationship = relationship;
+  }
+
+  @Override
+  public String getFromRole() throws EdmException {
+    return fromRole;
+  }
+
+  @Override
+  public String getToRole() throws EdmException {
+    return toRole;
+  }
+
+  @Override
+  public EdmAnnotations getAnnotations() throws EdmException {
+    return annotations;
+  }
+
+  @Override
+  public EdmMapping getMapping() throws EdmException {
+    return mapping;
+  }
+  
+  @Override
+  public String toString() {
+      return String.format(name);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmOnDeleteImpl.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmOnDeleteImpl.java b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmOnDeleteImpl.java
new file mode 100644
index 0000000..3f0fc01
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmOnDeleteImpl.java
@@ -0,0 +1,112 @@
+/*******************************************************************************
+ * 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.client.core.edm.Impl;
+
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.EdmAction;
+import org.apache.olingo.odata2.api.edm.EdmAnnotationAttribute;
+import org.apache.olingo.odata2.api.edm.EdmAnnotationElement;
+import org.apache.olingo.odata2.client.api.edm.EdmDocumentation;
+import org.apache.olingo.odata2.client.core.edm.EdmOnDelete;
+
+/**
+ * Objects of this class represent an OnDelete Action
+ * 
+ */
+public class EdmOnDeleteImpl implements EdmOnDelete{
+
+  private EdmAction action;
+  private EdmDocumentation documentation;
+  private List<EdmAnnotationAttribute> annotationAttributes;
+  private List<EdmAnnotationElement> annotationElements;
+
+  /**
+   * @return {@link EdmAction} action
+   */
+  public EdmAction getAction() {
+    return action;
+  }
+
+  /**
+   * @return {@link Documentation} documentation
+   */
+  public EdmDocumentation getDocumentation() {
+    return documentation;
+  }
+
+  /**
+   * @return List of {@link AnnotationAttribute} annotation attributes
+   */
+  public List<EdmAnnotationAttribute> getAnnotationAttributes() {
+    return annotationAttributes;
+  }
+
+  /**
+   * @return List of {@link AnnotationElement} annotation elements
+   */
+  public List<EdmAnnotationElement> getAnnotationElements() {
+    return annotationElements;
+  }
+
+  /**
+   * Sets the {@link EdmAction} for this {@link EdmOnDeleteImpl}
+   * @param action
+   * @return {@link EdmOnDeleteImpl} for method chaining
+   */
+  public EdmOnDeleteImpl setAction(final EdmAction action) {
+    this.action = action;
+    return this;
+  }
+
+  /**
+   * Sets the {@link Documentation} for this {@link EdmOnDeleteImpl}
+   * @param documentation
+   * @return {@link EdmOnDeleteImpl} for method chaining
+   */
+  public EdmOnDeleteImpl setDocumentation(final EdmDocumentation documentation) {
+    this.documentation = documentation;
+    return this;
+  }
+
+  /**
+   * Sets the List of {@link AnnotationAttribute} for this {@link EdmOnDeleteImpl}
+   * @param annotationAttributes
+   * @return {@link EdmOnDeleteImpl} for method chaining
+   */
+  public EdmOnDeleteImpl setAnnotationAttributes(final List<EdmAnnotationAttribute> annotationAttributes) {
+    this.annotationAttributes = annotationAttributes;
+    return this;
+  }
+
+  /**
+   * Sets the List of {@link AnnotationElement} for this {@link EdmOnDeleteImpl}
+   * @param annotationElements
+   * @return {@link EdmOnDeleteImpl} for method chaining
+   */
+  public EdmOnDeleteImpl setAnnotationElements(final List<EdmAnnotationElement> annotationElements) {
+    this.annotationElements = annotationElements;
+    return this;
+  }
+  
+  @Override
+  public String toString() {
+      return String.format(action.name());
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmParameterImpl.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmParameterImpl.java b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmParameterImpl.java
new file mode 100644
index 0000000..239c99d
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmParameterImpl.java
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ * 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.client.core.edm.Impl;
+
+import org.apache.olingo.odata2.api.edm.EdmAnnotatable;
+import org.apache.olingo.odata2.api.edm.EdmAnnotations;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmParameter;
+import org.apache.olingo.odata2.api.edm.EdmType;
+import org.apache.olingo.odata2.core.edm.EdmSimpleTypeFacadeImpl;
+
+/**
+ *  Objects of this class represent EdmParameter
+ */
+public class EdmParameterImpl extends EdmElementImpl implements EdmParameter, EdmAnnotatable {
+
+  private EdmFunctionImportParameter parameter;
+  private EdmAnnotations annotations;
+
+  
+  @Override
+  public EdmType getType() throws EdmException {
+    if (edmType == null) {
+      edmType = EdmSimpleTypeFacadeImpl.getEdmSimpleType(parameter.getType());
+      if (edmType == null) {
+        throw new EdmException(EdmException.TYPEPROBLEM);
+      }
+    }
+    return edmType;
+  }
+
+  /**
+   * @param parameter the parameter to set
+   */
+  public void setParameter(EdmFunctionImportParameter parameter) {
+    this.parameter = parameter;
+  }
+
+  @Override
+  public EdmAnnotations getAnnotations() throws EdmException {
+    return annotations;
+  }
+
+  /**
+   * @param annotations the annotations to set
+   */
+  public void setAnnotations(EdmAnnotations annotations) {
+    this.annotations = annotations;
+  }
+  
+  @Override
+  public String toString() {
+      return String.format(name);
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmPropertyImpl.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmPropertyImpl.java b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmPropertyImpl.java
new file mode 100644
index 0000000..91c0b00
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmPropertyImpl.java
@@ -0,0 +1,91 @@
+/*******************************************************************************
+ * 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.client.core.edm.Impl;
+
+import org.apache.olingo.odata2.api.edm.EdmAnnotatable;
+import org.apache.olingo.odata2.api.edm.EdmAnnotations;
+import org.apache.olingo.odata2.api.edm.EdmCustomizableFeedMappings;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmFacets;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.edm.provider.Mapping;
+import org.apache.olingo.odata2.client.api.edm.EdmDocumentation;
+
+/**
+ * Objects of this class represent EdmProperty
+ *
+ */
+public abstract class EdmPropertyImpl extends EdmElementImpl implements EdmProperty, EdmAnnotatable {
+
+  private EdmFacets facets;
+  private EdmCustomizableFeedMappings customizableFeedMappings;
+  private String mimeType;
+  private Mapping mapping;
+  private EdmDocumentation documentation;
+  private EdmAnnotations annotations;
+
+  public EdmFacets getFacets() {
+    return facets;
+  }
+
+  @Override
+  public void setFacets(EdmFacets facets) {
+    this.facets = facets;
+  }
+  
+  public void setMapping(Mapping mapping) {
+    this.mapping = mapping;
+  }
+
+  public void setDocumentation(EdmDocumentation documentation) {
+    this.documentation = documentation;
+  }
+
+  public void setCustomizableFeedMappings(EdmCustomizableFeedMappings customizableFeedMappings) {
+    this.customizableFeedMappings = customizableFeedMappings;
+  }
+
+  public void setMimeType(String mimeType) {
+    this.mimeType = mimeType;
+  }
+
+  @Override
+  public EdmCustomizableFeedMappings getCustomizableFeedMappings() throws EdmException {
+    return customizableFeedMappings;
+  }
+
+
+  public void setAnnotations(EdmAnnotations annotations) {
+    this.annotations = annotations;
+  }
+
+  @Override
+  public String getMimeType() throws EdmException {
+    return mimeType;
+  }
+
+  @Override
+  public EdmAnnotations getAnnotations() throws EdmException {
+    return annotations;
+  }
+  @Override
+  public String toString() {
+      return String.format(name);
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmPropertyRefImpl.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmPropertyRefImpl.java b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmPropertyRefImpl.java
new file mode 100644
index 0000000..864e979
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmPropertyRefImpl.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * 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.client.core.edm.Impl;
+
+
+/**
+ * Objects of this class represent a reference to a property via its name
+ * 
+ * 
+ */
+public class EdmPropertyRefImpl extends EdmPropertyImpl {
+
+  protected boolean isSimple;
+
+  /**
+   * @return <b>String</b> name of the {@link Property} this {@link EdmPropertyRefImpl} is referencing to
+   */
+
+  public void setIsSimple(boolean isSimple) {
+    this.isSimple = isSimple;
+  }
+
+  @Override
+  public boolean isSimple() {
+    return isSimple;
+  }
+  @Override
+  public String toString() {
+      return String.format(name);
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmReferentialConstraintImpl.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmReferentialConstraintImpl.java b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmReferentialConstraintImpl.java
new file mode 100644
index 0000000..131beaf
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmReferentialConstraintImpl.java
@@ -0,0 +1,72 @@
+/*******************************************************************************
+ * 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.client.core.edm.Impl;
+
+import org.apache.olingo.odata2.api.edm.EdmAnnotatable;
+import org.apache.olingo.odata2.api.edm.EdmAnnotations;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmReferentialConstraint;
+import org.apache.olingo.odata2.api.edm.EdmReferentialConstraintRole;
+
+/**
+ * Objects of this class represent EdmReferentialConstraint
+ *
+ */
+public class EdmReferentialConstraintImpl implements EdmReferentialConstraint, EdmAnnotatable {
+  private EdmAnnotations annotations;
+  private EdmReferentialConstraintRole referentialConstraintDependentRole;
+  private EdmReferentialConstraintRole referentialConstraintPrincipalRole;
+
+
+  @Override
+  public EdmReferentialConstraintRole getPrincipal() throws EdmException {
+    return referentialConstraintPrincipalRole;
+  }
+
+  @Override
+  public EdmReferentialConstraintRole getDependent() throws EdmException {
+    return referentialConstraintDependentRole;
+  }
+
+  @Override
+  public EdmAnnotations getAnnotations() throws EdmException {
+    return annotations;
+  }
+
+
+  public void setPrincipal(EdmReferentialConstraintRole referentialConstraintPrincipalRole) {
+    this.referentialConstraintPrincipalRole = referentialConstraintPrincipalRole;
+    
+  }
+
+  public void setDependent(EdmReferentialConstraintRole referentialConstraintDependentRole) {
+    this.referentialConstraintDependentRole = referentialConstraintDependentRole;
+    
+  }
+
+  public void setAnnotations(EdmAnnotations annotations) {
+    this.annotations = annotations;
+    
+  }
+  @Override
+  public String toString() {
+      return String.format("Dependent Role: " + referentialConstraintDependentRole.getRole() + 
+          "PrincipalRole: "+ referentialConstraintPrincipalRole);
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmReferentialConstraintRoleImpl.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmReferentialConstraintRoleImpl.java b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmReferentialConstraintRoleImpl.java
new file mode 100644
index 0000000..d370e43
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmReferentialConstraintRoleImpl.java
@@ -0,0 +1,98 @@
+/*******************************************************************************
+ * 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.client.core.edm.Impl;
+
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.EdmAnnotatable;
+import org.apache.olingo.odata2.api.edm.EdmAnnotations;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmReferentialConstraintRole;
+
+/**
+ * Objects of this class represent EdmReferentialConstraintRole
+ *
+ */
+public class EdmReferentialConstraintRoleImpl implements EdmReferentialConstraintRole, EdmAnnotatable {
+  protected List<String> refNames;
+  private EdmReferentialConstraintRole role;
+  private EdmAnnotations annotations;
+  private String roleName;
+  private List<EdmPropertyImpl> property;
+
+
+  public List<String> getRefNames() {
+    return refNames;
+  }
+
+  public void setRefNames(List<String> refNames) {
+    this.refNames = refNames;
+  }
+
+  public String getRoleName() {
+    return roleName;
+  }
+
+  @Override
+  public String getRole() {
+    return roleName;
+  }
+
+  /**
+   * @return the propertyRefs
+   */
+  public List<EdmPropertyImpl> getProperty() {
+    return property;
+  }
+
+  @Override
+  public List<String> getPropertyRefNames() {
+    return refNames;
+  }
+
+  @Override
+  public EdmAnnotations getAnnotations() throws EdmException {
+    return annotations;
+  }
+
+  /**
+   * @param role the role to set
+   */
+  public void setRole(EdmReferentialConstraintRole role) {
+    this.role = role;
+  }
+
+  public void setRoleName(String roleName) {
+    this.roleName = roleName;
+    
+  }
+
+  public void setProperty(List<EdmPropertyImpl> property) {
+    this.property = property;
+    
+  }
+
+  public void setAnnotations(EdmAnnotations annotations) {
+   this.annotations = annotations;
+    
+  }  @Override
+  public String toString() {
+    return String.format(role.getRole());
+}
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmSchemaImpl.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmSchemaImpl.java b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmSchemaImpl.java
new file mode 100644
index 0000000..68ec632
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmSchemaImpl.java
@@ -0,0 +1,205 @@
+/*******************************************************************************
+ * 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.client.core.edm.Impl;
+
+import java.util.List;
+import org.apache.olingo.odata2.client.api.edm.EdmSchema;
+import org.apache.olingo.odata2.client.api.edm.EdmUsing;
+import org.apache.olingo.odata2.api.edm.EdmEntityType;
+import org.apache.olingo.odata2.api.edm.EdmEntityContainer;
+import org.apache.olingo.odata2.api.edm.EdmAssociation;
+import org.apache.olingo.odata2.api.edm.EdmComplexType;
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmAnnotationAttribute;
+import org.apache.olingo.odata2.api.edm.EdmAnnotationElement;
+
+/**
+ * Objects of this class represent a schema
+ * 
+ */
+public class EdmSchemaImpl implements EdmSchema{
+
+  private String namespace;
+  private String alias;
+  private List<EdmUsing > usings;
+  private List<EdmEntityType> entityTypes;
+  private List<EdmComplexType> complexTypes;
+  private List<EdmAssociation> associations;
+  private List<EdmEntityContainer> entityContainers;
+  private List<EdmAnnotationAttribute> annotationAttributes;
+  private List<EdmAnnotationElement> annotationElements;
+
+  /**
+   * Sets the namespace for this {@link EdmSchemaImpl}
+   * @param namespace
+   * @return {@link EdmSchemaImpl} for method chaining
+   */
+  public EdmSchemaImpl setNamespace(final String namespace) {
+    this.namespace = namespace;
+    return this;
+  }
+
+  /**
+   * Sets the alias for this {@link EdmSchemaImpl}
+   * @param alias
+   * @return {@link EdmSchemaImpl} for method chaining
+   */
+  public EdmSchemaImpl setAlias(final String alias) {
+    this.alias = alias;
+    return this;
+  }
+
+  /**
+   * Sets the {@link Using} for this {@link EdmSchemaImpl}
+   * @param usings
+   * @return {@link EdmSchemaImpl} for method chaining
+   */
+  public EdmSchemaImpl setUsings(final List<EdmUsing> usings) {
+    this.usings = usings;
+    return this;
+  }
+
+  /**
+   * Sets the {@link EntityType}s for this {@link EdmSchemaImpl}
+   * @param entityTypes
+   * @return {@link EdmSchemaImpl} for method chaining
+   */
+  public EdmSchemaImpl setEntityTypes(final List<EdmEntityType> entityTypes) {
+    this.entityTypes = entityTypes;
+    return this;
+  }
+
+  /**
+   * Sets the {@link ComplexType}s for this {@link EdmSchemaImpl}
+   * @param complexTypes
+   * @return {@link EdmSchemaImpl} for method chaining
+   */
+  public EdmSchemaImpl setComplexTypes(final List<EdmComplexType> complexTypes) {
+    this.complexTypes = complexTypes;
+    return this;
+  }
+
+  /**
+   * Sets the {@link Association}s for this {@link EdmSchemaImpl}
+   * @param associations
+   * @return {@link EdmSchemaImpl} for method chaining
+   */
+  public EdmSchemaImpl setAssociations(final List<EdmAssociation> associations) {
+    this.associations = associations;
+    return this;
+  }
+
+  /**
+   * Sets the {@link EntityContainer}s for this {@link EdmSchemaImpl}
+   * @param entityContainers
+   * @return {@link EdmSchemaImpl} for method chaining
+   */
+  public EdmSchemaImpl setEntityContainers(final List<EdmEntityContainer> entityContainers) {
+    this.entityContainers = entityContainers;
+    return this;
+  }
+
+  /**
+   * Sets the List of {@link AnnotationAttribute} for this {@link EdmSchemaImpl}
+   * @param annotationAttributes
+   * @return {@link EdmSchemaImpl} for method chaining
+   */
+  public EdmSchemaImpl setAnnotationAttributes(final List<EdmAnnotationAttribute> annotationAttributes) {
+    this.annotationAttributes = annotationAttributes;
+    return this;
+  }
+
+  /**
+   * Sets the List of {@link AnnotationElement} for this {@link EdmSchemaImpl}
+   * @param annotationElements
+   * @return {@link EdmSchemaImpl} for method chaining
+   */
+  public EdmSchemaImpl setAnnotationElements(final List<EdmAnnotationElement> annotationElements) {
+    this.annotationElements = annotationElements;
+    return this;
+  }
+
+  /**
+   * @return <b>String</b> namespace of this {@link EdmSchemaImpl}
+   */
+  public String getNamespace() {
+    return namespace;
+  }
+
+  /**
+   * @return <b>String</b> alias of this {@link EdmSchemaImpl}
+   */
+  public String getAlias() {
+    return alias;
+  }
+
+  /**
+   * @return List<{@link Using}> of this {@link EdmSchemaImpl}
+   */
+  public List<EdmUsing> getUsings() {
+    return usings;
+  }
+
+  /**
+   * @return List<{@link EntityType}> of this {@link EdmSchemaImpl}
+   */
+  public List<EdmEntityType> getEntityTypes() {
+    return entityTypes;
+  }
+
+  /**
+   * @return List<{@link ComplexType}> of this {@link EdmSchemaImpl}
+   */
+  public List<EdmComplexType> getComplexTypes() {
+    return complexTypes;
+  }
+
+  /**
+   * @return List<{@link Association}> of this {@link EdmSchemaImpl}
+   */
+  public List<EdmAssociation> getAssociations() {
+    return associations;
+  }
+
+  /**
+   * @return List<{@link EntityContainer}> of this {@link EdmSchemaImpl}
+   */
+  public List<EdmEntityContainer> getEntityContainers() {
+    return entityContainers;
+  }
+
+  /**
+   * @return List of {@link AnnotationAttribute} annotation attributes
+   */
+  public List<EdmAnnotationAttribute> getAnnotationAttributes() {
+    return annotationAttributes;
+  }
+
+  /**
+   * @return List of {@link AnnotationElement} annotation elements
+   */
+  public List<EdmAnnotationElement> getAnnotationElements() {
+    return annotationElements;
+  }
+  
+  @Override
+  public String toString() {
+      return String.format(namespace + Edm.DELIMITER  + alias);
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmSimplePropertyImpl.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmSimplePropertyImpl.java b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmSimplePropertyImpl.java
new file mode 100644
index 0000000..07c97f7
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmSimplePropertyImpl.java
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * 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.client.core.edm.Impl;
+
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeKind;
+import org.apache.olingo.odata2.api.edm.EdmType;
+import org.apache.olingo.odata2.core.edm.EdmSimpleTypeFacadeImpl;
+
+/**
+ * Objects of this class represent EdmSimpleProperty
+ *
+ */
+public class EdmSimplePropertyImpl extends EdmPropertyImpl {
+
+  private EdmSimpleTypeKind simpleType;
+
+  @Override
+  public EdmType getType() throws EdmException {
+    if (edmType == null) {
+      edmType = EdmSimpleTypeFacadeImpl.getEdmSimpleType(getSimpleType());
+      if (edmType == null) {
+        throw new EdmException(EdmException.TYPEPROBLEM);
+      }
+    }
+    return edmType;
+  }
+
+  public EdmSimpleTypeKind getSimpleType() {
+    return simpleType;
+  }
+
+  public void setSimpleType(EdmSimpleTypeKind simpleType) {
+    this.simpleType = simpleType;
+  }
+
+  @Override
+  public boolean isSimple() {
+    return true;
+  }
+  
+  @Override
+  public String toString() {
+      return String.format(name);
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmStructuralTypeImpl.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmStructuralTypeImpl.java b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmStructuralTypeImpl.java
new file mode 100644
index 0000000..6a91ecf
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmStructuralTypeImpl.java
@@ -0,0 +1,154 @@
+/*******************************************************************************
+ * 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.client.core.edm.Impl;
+
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmAnnotatable;
+import org.apache.olingo.odata2.api.edm.EdmAnnotations;
+import org.apache.olingo.odata2.api.edm.EdmComplexType;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmMapping;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.edm.EdmStructuralType;
+import org.apache.olingo.odata2.api.edm.EdmTypeKind;
+import org.apache.olingo.odata2.api.edm.EdmTyped;
+
+/**
+ *  Objects of this class represent structural type of the entity 
+ */
+public abstract class EdmStructuralTypeImpl extends EdmNamedImpl implements EdmStructuralType, EdmAnnotatable {
+
+  protected EdmStructuralType edmBaseType;
+  protected EdmComplexType structuralType;
+  private EdmTypeKind edmTypeKind;
+  protected String namespace;
+  private List<EdmProperty> properties;
+  private List<String> edmPropertyNames;
+  private EdmAnnotations annotations;
+
+
+  public EdmStructuralType getEdmBaseType() {
+    return edmBaseType;
+  }
+
+  public void setEdmBaseType(EdmStructuralType edmBaseType) {
+    this.edmBaseType = edmBaseType;
+  }
+
+  public EdmComplexType getStructuralType() {
+    return structuralType;
+  }
+
+  public void setStructuralType(EdmComplexType structuralType) {
+    this.structuralType = structuralType;
+  }
+
+  public EdmTypeKind getEdmTypeKind() {
+    return edmTypeKind;
+  }
+
+  public void setEdmTypeKind(EdmTypeKind edmTypeKind) {
+    this.edmTypeKind = edmTypeKind;
+  }
+
+  public void setEdmPropertyNames(List<String> edmPropertyNames) {
+    this.edmPropertyNames = edmPropertyNames;
+  }
+
+  public void setNamespace(String namespace) {
+    this.namespace = namespace;
+  }
+
+  public void setAnnotations(EdmAnnotations annotations) {
+    this.annotations = annotations;
+  }
+
+
+  public List<EdmProperty> getProperties() {
+    return properties;
+  }
+
+  public void setProperties(List<EdmProperty> properties) {
+    this.properties = properties;
+  }
+
+  @Override
+  public String getNamespace() throws EdmException {
+    return namespace;
+  }
+
+  @Override
+  public EdmTyped getProperty(final String name) throws EdmException {
+    EdmTyped property = getPropertyInternal(name);
+    if (property == null && edmBaseType != null) {
+      property = edmBaseType.getProperty(name);
+    }
+    return property;
+  }
+
+  @Override
+  public List<String> getPropertyNames() throws EdmException {
+    return edmPropertyNames;
+  }
+
+  @Override
+  public EdmStructuralType getBaseType() throws EdmException {
+    return edmBaseType;
+  }
+
+  @Override
+  public EdmTypeKind getKind() {
+    return edmTypeKind;
+  }
+
+  @Override
+  public EdmMapping getMapping() throws EdmException {
+    return structuralType.getMapping();
+  }
+
+  protected EdmTyped getPropertyInternal(final String name) throws EdmException {
+    EdmTyped edmProperty = null;
+    for (EdmProperty property : properties) {
+      if (property.getName().equals(name)) {
+        return property;
+      } 
+    }
+    if (edmBaseType!=null) {
+      edmProperty = edmBaseType.getProperty(name);
+    }
+    return edmProperty;
+  }
+
+  @Override
+  public String toString() {
+    try {
+      return namespace + Edm.DELIMITER + getName();
+    } catch (final EdmException e) {
+      return null; //NOSONAR
+    }
+  }
+
+  @Override
+  public EdmAnnotations getAnnotations() throws EdmException {
+    return annotations;
+  }
+  
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmTypedImpl.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmTypedImpl.java b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmTypedImpl.java
new file mode 100644
index 0000000..597d426
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmTypedImpl.java
@@ -0,0 +1,84 @@
+/*******************************************************************************
+ * 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.client.core.edm.Impl;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
+import org.apache.olingo.odata2.api.edm.EdmSimpleType;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeKind;
+import org.apache.olingo.odata2.api.edm.EdmType;
+import org.apache.olingo.odata2.api.edm.EdmTyped;
+import org.apache.olingo.odata2.api.edm.FullQualifiedName;
+import org.apache.olingo.odata2.core.edm.EdmSimpleTypeFacadeImpl;
+
+/**
+ *  Objects of this class represent type of the entity
+ */
+public class EdmTypedImpl extends EdmNamedImpl implements EdmTyped {
+
+  protected EdmType edmType;
+  protected FullQualifiedName typeName;
+  protected EdmMultiplicity multiplicity;
+
+  public void setEdmType(EdmType edmType) {
+    this.edmType = edmType;
+  }
+
+  public EdmTypedImpl setTypeName(FullQualifiedName typeName) {
+    this.typeName = typeName;
+    return this;
+  }
+
+  public EdmTypedImpl setMultiplicity(EdmMultiplicity multiplicity) {
+    this.multiplicity = multiplicity;
+    return this;
+  }
+
+  @Override
+  public EdmType getType() throws EdmException {
+    if (edmType == null) {
+      final String namespace = typeName.getNamespace();
+      if (EdmSimpleType.EDM_NAMESPACE.equals(typeName.getNamespace())) {
+        edmType = EdmSimpleTypeFacadeImpl.getEdmSimpleType(EdmSimpleTypeKind.valueOf(typeName.getName()));
+      } else {
+        edmType = edm.getComplexType(namespace, typeName.getName());
+      }
+      if (edmType == null) {
+        edmType = edm.getEntityType(namespace, typeName.getName());
+      }
+
+      if (edmType == null) {
+        throw new EdmException(EdmException.TYPEPROBLEM);
+      }
+
+    }
+    return edmType;
+  }
+
+  @Override
+  public EdmMultiplicity getMultiplicity() throws EdmException {
+    return multiplicity;
+  }
+  
+  @Override
+  public String toString() {
+    return typeName.getNamespace() + Edm.DELIMITER + typeName.getName();
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmUsingImpl.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmUsingImpl.java b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmUsingImpl.java
new file mode 100644
index 0000000..0bfdec2
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/edm/Impl/EdmUsingImpl.java
@@ -0,0 +1,129 @@
+/*******************************************************************************
+ * 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.client.core.edm.Impl;
+
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmAnnotationAttribute;
+import org.apache.olingo.odata2.api.edm.EdmAnnotationElement;
+import org.apache.olingo.odata2.client.api.edm.EdmUsing;
+
+/**
+ *  Objects of this class represent EdmUsing
+ */
+public class EdmUsingImpl implements EdmUsing{
+
+  private String namespace;
+  private String alias;
+  private EdmDocumentationImpl documentation;
+  private List<EdmAnnotationAttribute> annotationAttributes;
+  private List<EdmAnnotationElement> annotationElements;
+
+  /**
+   * Sets the namespace for this {@link EdmUsingImpl}
+   * @param namespace
+   * @return {@link EdmUsingImpl} for method chaining
+   */
+  public EdmUsingImpl setNamespace(final String namespace) {
+    this.namespace = namespace;
+    return this;
+  }
+
+  /**
+   * Sets the alias for this {@link EdmUsingImpl}
+   * @param alias
+   * @return {@link EdmUsingImpl} for method chaining
+   */
+  public EdmUsingImpl setAlias(final String alias) {
+    this.alias = alias;
+    return this;
+  }
+
+  /**
+   * Sets the {@link EdmDocumentation} for this {@link EdmUsingImpl}
+   * @param documentation
+   * @return {@link EdmUsingImpl} for method chaining
+   */
+  public EdmUsingImpl setDocumentation(final EdmDocumentationImpl documentation) {
+    this.documentation = documentation;
+    return this;
+  }
+
+  /**
+   * Sets the collection of {@link AnnotationAttribute} for this {@link EdmUsingImpl}
+   * @param annotationAttributes
+   * @return {@link EdmUsingImpl} for method chaining
+   */
+  public EdmUsingImpl setAnnotationAttributes(final List<EdmAnnotationAttribute> annotationAttributes) {
+    this.annotationAttributes = annotationAttributes;
+    return this;
+  }
+
+  /**
+   * Sets the collection of {@link AnnotationElement} for this {@link EdmUsingImpl}
+   * @param annotationElements
+   * @return {@link EdmUsingImpl} for method chaining
+   */
+  public EdmUsingImpl setAnnotationElements(final List<EdmAnnotationElement> annotationElements) {
+    this.annotationElements = annotationElements;
+    return this;
+  }
+
+  /**
+   * @return <b>String</b> namespace
+   */
+  public String getNamespace() {
+    return namespace;
+  }
+
+  /**
+   * @return <b>String</b> alias
+   */
+  public String getAlias() {
+    return alias;
+  }
+
+  /**
+   * @return {@link EdmDocumentation} documentation
+   */
+  public EdmDocumentationImpl getDocumentation() {
+    return documentation;
+  }
+
+  /**
+   * @return collection of {@link AnnotationAttribute} annotation attributes
+   */
+  public Collection<EdmAnnotationAttribute> getAnnotationAttributes() {
+    return annotationAttributes;
+  }
+
+  /**
+   * @return collection of {@link AnnotationElement} annotation elements
+   */
+  public Collection<EdmAnnotationElement> getAnnotationElements() {
+    return annotationElements;
+  }
+  
+  @Override
+  public String toString() {
+    return namespace + Edm.DELIMITER + alias;
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/AtomSerializerDeserializer.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/AtomSerializerDeserializer.java b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/AtomSerializerDeserializer.java
new file mode 100644
index 0000000..0298567
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/AtomSerializerDeserializer.java
@@ -0,0 +1,211 @@
+/*******************************************************************************
+ * 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.client.core.ep;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.List;
+
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+
+import org.apache.olingo.odata2.api.batch.BatchException;
+import org.apache.olingo.odata2.api.batch.BatchResponsePart;
+import org.apache.olingo.odata2.api.client.batch.BatchPart;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmFunctionImport;
+import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
+import org.apache.olingo.odata2.api.edm.EdmTypeKind;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.ep.entry.ODataEntry;
+import org.apache.olingo.odata2.api.ep.feed.ODataFeed;
+import org.apache.olingo.odata2.api.processor.ODataErrorContext;
+import org.apache.olingo.odata2.api.processor.ODataResponse;
+import org.apache.olingo.odata2.api.processor.ODataResponse.ODataResponseBuilder;
+import org.apache.olingo.odata2.client.api.ep.ContentTypeBasedDeserializer;
+import org.apache.olingo.odata2.client.api.ep.ContentTypeBasedSerializer;
+import org.apache.olingo.odata2.client.api.ep.Entity;
+import org.apache.olingo.odata2.client.api.ep.EntityCollection;
+import org.apache.olingo.odata2.client.api.ep.EntityCollectionSerializerProperties;
+import org.apache.olingo.odata2.client.api.ep.EntitySerializerProperties;
+import org.apache.olingo.odata2.client.api.ep.EntityStream;
+import org.apache.olingo.odata2.client.core.ep.deserializer.XmlEntityDeserializer;
+import org.apache.olingo.odata2.client.core.ep.deserializer.XmlErrorDocumentDeserializer;
+import org.apache.olingo.odata2.client.core.ep.serializer.AtomEntryEntitySerializer;
+import org.apache.olingo.odata2.client.core.ep.serializer.AtomFeedSerializer;
+import org.apache.olingo.odata2.core.batch.BatchRequestWriter;
+import org.apache.olingo.odata2.core.batch.BatchResponseWriter;
+import org.apache.olingo.odata2.core.commons.ContentType;
+import org.apache.olingo.odata2.core.commons.ContentType.ODataFormat;
+import org.apache.olingo.odata2.core.commons.XmlHelper;
+import org.apache.olingo.odata2.core.ep.EntityProviderProducerException;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityInfoAggregator;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityPropertyInfo;
+import org.apache.olingo.odata2.core.ep.util.CircleStreamBuffer;
+
+/**
+ *  This class includes methods to serialize deserialize XML Content type
+ */
+public class AtomSerializerDeserializer implements ContentTypeBasedSerializer, ContentTypeBasedDeserializer {
+
+  /** Default used charset for writer and response content header */
+  private static final String DEFAULT_CHARSET = ContentType.CHARSET_UTF_8;
+  private static final String XML_VERSION = "1.0";
+
+  /**
+   * 
+   * @throws EntityProviderException
+   */
+  public AtomSerializerDeserializer() throws EntityProviderException {
+    this(ODataFormat.ATOM);
+  }
+
+  /**
+   * 
+   * @param odataFormat
+   * @throws EntityProviderException
+   */
+  public AtomSerializerDeserializer(final ODataFormat odataFormat) throws EntityProviderException {
+    if (odataFormat != ODataFormat.ATOM && odataFormat != ODataFormat.XML) {
+      throw new EntityProviderException(EntityProviderException.ILLEGAL_ARGUMENT
+          .addContent("Got unsupported ODataFormat '" + odataFormat + "'."));
+    }
+  }
+
+
+  @Override
+  public ODataResponse writeEntry( EdmEntitySet entitySet, Entity data
+      ) throws EntityProviderException {
+
+    CircleStreamBuffer csb = new CircleStreamBuffer();
+    
+    try {
+      if(data == null){
+        throw new EntityProviderProducerException(EntityProviderException.NULL_VALUE);
+      }
+      OutputStream outStream = csb.getOutputStream();
+      XMLStreamWriter writer = XmlHelper.getXMLOutputFactory().createXMLStreamWriter(outStream, DEFAULT_CHARSET);
+      writer.writeStartDocument(DEFAULT_CHARSET, XML_VERSION);
+      EntitySerializerProperties properties = data.getWriteProperties();
+      AtomEntryEntitySerializer as = new AtomEntryEntitySerializer(properties );
+      EntityInfoAggregator eia = EntityInfoAggregator.create(entitySet, null);
+      as.append(writer, eia, data, true, false);
+
+      writer.flush();
+      csb.closeWrite();
+
+      ODataResponseBuilder response = ODataResponse.entity(csb.getInputStream());
+      return response.build();
+    } catch (EntityProviderException e) {
+      csb.close();
+      throw e;
+    } catch (Exception e) {
+      csb.close();
+      throw new EntityProviderProducerException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass()
+          .getSimpleName()), e);
+    }
+  
+  }
+
+  @Override
+  public ODataFeed readFeed( EdmEntitySet entitySet, EntityStream content)
+      throws EntityProviderException {
+    XmlEntityDeserializer xec = new XmlEntityDeserializer();
+    return xec.readFeed(entitySet, content);
+  }
+
+  @Override
+  public ODataEntry readEntry( EdmEntitySet entitySet, EntityStream content)
+      throws EntityProviderException {
+
+    XmlEntityDeserializer xec = new XmlEntityDeserializer();
+    return xec.readEntry(entitySet, content);
+  
+  }
+
+  @Override
+  public ODataErrorContext readErrorDocument(InputStream errorDocument) throws EntityProviderException {
+    XmlErrorDocumentDeserializer xmlErrorDocumentConsumer = new XmlErrorDocumentDeserializer();
+    return xmlErrorDocumentConsumer.readError(errorDocument);
+  }
+
+  @Override
+  public ODataResponse writeFeed(EdmEntitySet entitySet, EntityCollection data) throws EntityProviderException {
+    CircleStreamBuffer csb = new CircleStreamBuffer();
+
+    try {
+      if(data == null){
+        throw new EntityProviderProducerException(EntityProviderException.NULL_VALUE);
+      }
+      
+      OutputStream outStream = csb.getOutputStream();
+      XMLStreamWriter writer = XmlHelper.getXMLOutputFactory().createXMLStreamWriter(outStream, DEFAULT_CHARSET);
+      writer.writeStartDocument(DEFAULT_CHARSET, XML_VERSION);
+
+      EntityCollectionSerializerProperties properties = data.getCollectionProperties();
+      AtomFeedSerializer atomFeedProvider = new AtomFeedSerializer(properties);
+      EntityInfoAggregator eia = EntityInfoAggregator.create(entitySet, null);
+      atomFeedProvider.append(writer, eia, data, false);
+
+      writer.flush();
+      csb.closeWrite();
+
+      return ODataResponse.entity(csb.getInputStream()).build();
+    } catch (EntityProviderException e) {
+      csb.close();
+      throw e;
+    } catch (XMLStreamException e) {
+      csb.close();
+      throw new EntityProviderProducerException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass()
+          .getSimpleName()), e);
+    }
+  }
+
+  @Override
+  public InputStream readBatchRequest(List<BatchPart> batchParts, String boundary) {
+    BatchRequestWriter batchWriter = new BatchRequestWriter();
+    return batchWriter.writeBatchRequest(batchParts, boundary);
+  }
+
+  @Override
+  public ODataResponse writeBatchResponse(List<BatchResponsePart> batchResponseParts) throws BatchException {
+    BatchResponseWriter batchWriter = new BatchResponseWriter();
+    return batchWriter.writeResponse(batchResponseParts);
+  }
+
+  @Override
+  public Object readFunctionImport(EdmFunctionImport functionImport, EntityStream content)
+      throws EntityProviderException {
+    try {
+      if (functionImport.getReturnType().getType().getKind() == EdmTypeKind.ENTITY) {
+        return functionImport.getReturnType().getMultiplicity() == EdmMultiplicity.MANY
+            ? new XmlEntityDeserializer().readFeed(functionImport.getEntitySet(), content)
+            : new XmlEntityDeserializer().readEntry(functionImport.getEntitySet(), content);
+      } else {
+        final EntityPropertyInfo info = EntityInfoAggregator.create(functionImport);
+        return functionImport.getReturnType().getMultiplicity() == EdmMultiplicity.MANY ?
+          new XmlEntityDeserializer().readCollection(info, content) :
+          new XmlEntityDeserializer().readProperty(info, content).get(info.getName());
+      }
+    } catch (final EdmException e) {
+      throw new EntityProviderException(e.getMessageReference(), e);
+    }
+  }
+}


[02/24] olingo-odata2 git commit: [OLINGO-1253]Client Module for Olingo v2

Posted by ar...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/resources/ProductsFeed.xml
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/resources/ProductsFeed.xml b/odata2-lib/odata-client-core/src/test/resources/ProductsFeed.xml
new file mode 100644
index 0000000..23a4eb0
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/resources/ProductsFeed.xml
@@ -0,0 +1,474 @@
+<!--
+  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.
+-->
+<feed xml:base="http://services.odata.org/(S(tcjpjrwvrq5cbwf1yqulu1hc))/V2/OData/OData.svc/" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns="http://www.w3.org/2005/Atom">
+  <title type="text">Products</title>
+  <id>http://services.odata.org/(S(tcjpjrwvrq5cbwf1yqulu1hc))/V2/OData/OData.svc/Products/</id>
+  <updated>2017-04-07T05:44:22Z</updated>
+  <link rel="self" title="Products" href="Products" />
+  <entry>
+    <id>http://services.odata.org/(S(tcjpjrwvrq5cbwf1yqulu1hc))/V2/OData/OData.svc/Products(0)</id>
+    <title type="text">Bread</title>
+    <summary type="text">Whole grain bread</summary>
+    <updated>2017-04-07T05:44:22Z</updated>
+    <author>
+      <name />
+    </author>
+    <link rel="edit" title="Product" href="Products(0)" />
+    <link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/Category" type="application/atom+xml;type=entry" title="Category" href="Products(0)/Category" />
+    <link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/Supplier" type="application/atom+xml;type=entry" title="Supplier" href="Products(0)/Supplier">
+      <m:inline>
+        <entry m:etag="W/&quot;0&quot;">
+          <id>http://services.odata.org/(S(tcjpjrwvrq5cbwf1yqulu1hc))/V2/OData/OData.svc/Suppliers(1)</id>
+          <title type="text">Tokyo Traders</title>
+          <updated>2017-04-07T05:44:22Z</updated>
+          <author>
+            <name />
+          </author>
+          <link rel="edit" title="Supplier" href="Suppliers(1)" />
+          <link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/Products" type="application/atom+xml;type=feed" title="Products" href="Suppliers(1)/Products" />
+          <category term="ODataDemo.Supplier" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+          <content type="application/xml">
+            <m:properties>
+              <d:ID m:type="Edm.Int32">1</d:ID>
+              <d:Name>Tokyo Traders</d:Name>
+              <d:Concurrency m:type="Edm.Int32">0</d:Concurrency>
+              <d:Address m:type="ODataDemo.Address">
+                <d:Street>NE 40th</d:Street>
+                <d:City>Redmond</d:City>
+                <d:State>WA</d:State>
+                <d:ZipCode>98052</d:ZipCode>
+                <d:Country>USA</d:Country>
+              </d:Address>
+            </m:properties>
+          </content>
+        </entry>
+      </m:inline>
+    </link>
+    <category term="ODataDemo.Product" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+    <content type="application/xml">
+      <m:properties>
+        <d:ID m:type="Edm.Int32">0</d:ID>
+        <d:ReleaseDate m:type="Edm.DateTime">1992-01-01T00:00:00</d:ReleaseDate>
+        <d:DiscontinuedDate m:type="Edm.DateTime" m:null="true" />
+        <d:Rating m:type="Edm.Int32">4</d:Rating>
+        <d:Price m:type="Edm.Decimal">2.5</d:Price>
+      </m:properties>
+    </content>
+  </entry>
+  <entry>
+    <id>http://services.odata.org/(S(tcjpjrwvrq5cbwf1yqulu1hc))/V2/OData/OData.svc/Products(1)</id>
+    <title type="text">Milk</title>
+    <summary type="text">Low fat milk</summary>
+    <updated>2017-04-07T05:44:22Z</updated>
+    <author>
+      <name />
+    </author>
+    <link rel="edit" title="Product" href="Products(1)" />
+    <link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/Category" type="application/atom+xml;type=entry" title="Category" href="Products(1)/Category" />
+    <link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/Supplier" type="application/atom+xml;type=entry" title="Supplier" href="Products(1)/Supplier">
+      <m:inline>
+        <entry m:etag="W/&quot;0&quot;">
+          <id>http://services.odata.org/(S(tcjpjrwvrq5cbwf1yqulu1hc))/V2/OData/OData.svc/Suppliers(0)</id>
+          <title type="text">Exotic Liquids</title>
+          <updated>2017-04-07T05:44:22Z</updated>
+          <author>
+            <name />
+          </author>
+          <link rel="edit" title="Supplier" href="Suppliers(0)" />
+          <link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/Products" type="application/atom+xml;type=feed" title="Products" href="Suppliers(0)/Products" />
+          <category term="ODataDemo.Supplier" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+          <content type="application/xml">
+            <m:properties>
+              <d:ID m:type="Edm.Int32">0</d:ID>
+              <d:Name>Exotic Liquids</d:Name>
+              <d:Concurrency m:type="Edm.Int32">0</d:Concurrency>
+              <d:Address m:type="ODataDemo.Address">
+                <d:Street>NE 228th</d:Street>
+                <d:City>Sammamish</d:City>
+                <d:State>WA</d:State>
+                <d:ZipCode>98074</d:ZipCode>
+                <d:Country>USA</d:Country>
+              </d:Address>
+            </m:properties>
+          </content>
+        </entry>
+      </m:inline>
+    </link>
+    <category term="ODataDemo.Product" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+    <content type="application/xml">
+      <m:properties>
+        <d:ID m:type="Edm.Int32">1</d:ID>
+        <d:ReleaseDate m:type="Edm.DateTime">1995-10-01T00:00:00</d:ReleaseDate>
+        <d:DiscontinuedDate m:type="Edm.DateTime" m:null="true" />
+        <d:Rating m:type="Edm.Int32">3</d:Rating>
+        <d:Price m:type="Edm.Decimal">3.5</d:Price>
+      </m:properties>
+    </content>
+  </entry>
+  <entry>
+    <id>http://services.odata.org/(S(tcjpjrwvrq5cbwf1yqulu1hc))/V2/OData/OData.svc/Products(2)</id>
+    <title type="text">Vint soda</title>
+    <summary type="text">Americana Variety - Mix of 6 flavors</summary>
+    <updated>2017-04-07T05:44:22Z</updated>
+    <author>
+      <name />
+    </author>
+    <link rel="edit" title="Product" href="Products(2)" />
+    <link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/Category" type="application/atom+xml;type=entry" title="Category" href="Products(2)/Category" />
+    <link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/Supplier" type="application/atom+xml;type=entry" title="Supplier" href="Products(2)/Supplier">
+      <m:inline>
+        <entry m:etag="W/&quot;0&quot;">
+          <id>http://services.odata.org/(S(tcjpjrwvrq5cbwf1yqulu1hc))/V2/OData/OData.svc/Suppliers(0)</id>
+          <title type="text">Exotic Liquids</title>
+          <updated>2017-04-07T05:44:22Z</updated>
+          <author>
+            <name />
+          </author>
+          <link rel="edit" title="Supplier" href="Suppliers(0)" />
+          <link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/Products" type="application/atom+xml;type=feed" title="Products" href="Suppliers(0)/Products" />
+          <category term="ODataDemo.Supplier" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+          <content type="application/xml">
+            <m:properties>
+              <d:ID m:type="Edm.Int32">0</d:ID>
+              <d:Name>Exotic Liquids</d:Name>
+              <d:Concurrency m:type="Edm.Int32">0</d:Concurrency>
+              <d:Address m:type="ODataDemo.Address">
+                <d:Street>NE 228th</d:Street>
+                <d:City>Sammamish</d:City>
+                <d:State>WA</d:State>
+                <d:ZipCode>98074</d:ZipCode>
+                <d:Country>USA</d:Country>
+              </d:Address>
+            </m:properties>
+          </content>
+        </entry>
+      </m:inline>
+    </link>
+    <category term="ODataDemo.Product" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+    <content type="application/xml">
+      <m:properties>
+        <d:ID m:type="Edm.Int32">2</d:ID>
+        <d:ReleaseDate m:type="Edm.DateTime">2000-10-01T00:00:00</d:ReleaseDate>
+        <d:DiscontinuedDate m:type="Edm.DateTime" m:null="true" />
+        <d:Rating m:type="Edm.Int32">3</d:Rating>
+        <d:Price m:type="Edm.Decimal">20.9</d:Price>
+      </m:properties>
+    </content>
+  </entry>
+  <entry>
+    <id>http://services.odata.org/(S(tcjpjrwvrq5cbwf1yqulu1hc))/V2/OData/OData.svc/Products(3)</id>
+    <title type="text">Havina Cola</title>
+    <summary type="text">The Original Key Lime Cola</summary>
+    <updated>2017-04-07T05:44:22Z</updated>
+    <author>
+      <name />
+    </author>
+    <link rel="edit" title="Product" href="Products(3)" />
+    <link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/Category" type="application/atom+xml;type=entry" title="Category" href="Products(3)/Category" />
+    <link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/Supplier" type="application/atom+xml;type=entry" title="Supplier" href="Products(3)/Supplier">
+      <m:inline>
+        <entry m:etag="W/&quot;0&quot;">
+          <id>http://services.odata.org/(S(tcjpjrwvrq5cbwf1yqulu1hc))/V2/OData/OData.svc/Suppliers(0)</id>
+          <title type="text">Exotic Liquids</title>
+          <updated>2017-04-07T05:44:22Z</updated>
+          <author>
+            <name />
+          </author>
+          <link rel="edit" title="Supplier" href="Suppliers(0)" />
+          <link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/Products" type="application/atom+xml;type=feed" title="Products" href="Suppliers(0)/Products" />
+          <category term="ODataDemo.Supplier" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+          <content type="application/xml">
+            <m:properties>
+              <d:ID m:type="Edm.Int32">0</d:ID>
+              <d:Name>Exotic Liquids</d:Name>
+              <d:Concurrency m:type="Edm.Int32">0</d:Concurrency>
+              <d:Address m:type="ODataDemo.Address">
+                <d:Street>NE 228th</d:Street>
+                <d:City>Sammamish</d:City>
+                <d:State>WA</d:State>
+                <d:ZipCode>98074</d:ZipCode>
+                <d:Country>USA</d:Country>
+              </d:Address>
+            </m:properties>
+          </content>
+        </entry>
+      </m:inline>
+    </link>
+    <category term="ODataDemo.Product" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+    <content type="application/xml">
+      <m:properties>
+        <d:ID m:type="Edm.Int32">3</d:ID>
+        <d:ReleaseDate m:type="Edm.DateTime">2005-10-01T00:00:00</d:ReleaseDate>
+        <d:DiscontinuedDate m:type="Edm.DateTime">2006-10-01T00:00:00</d:DiscontinuedDate>
+        <d:Rating m:type="Edm.Int32">3</d:Rating>
+        <d:Price m:type="Edm.Decimal">19.9</d:Price>
+      </m:properties>
+    </content>
+  </entry>
+  <entry>
+    <id>http://services.odata.org/(S(tcjpjrwvrq5cbwf1yqulu1hc))/V2/OData/OData.svc/Products(4)</id>
+    <title type="text">Fruit Punch</title>
+    <summary type="text">Mango flavor, 8.3 Ounce Cans (Pack of 24)</summary>
+    <updated>2017-04-07T05:44:22Z</updated>
+    <author>
+      <name />
+    </author>
+    <link rel="edit" title="Product" href="Products(4)" />
+    <link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/Category" type="application/atom+xml;type=entry" title="Category" href="Products(4)/Category" />
+    <link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/Supplier" type="application/atom+xml;type=entry" title="Supplier" href="Products(4)/Supplier">
+      <m:inline>
+        <entry m:etag="W/&quot;0&quot;">
+          <id>http://services.odata.org/(S(tcjpjrwvrq5cbwf1yqulu1hc))/V2/OData/OData.svc/Suppliers(0)</id>
+          <title type="text">Exotic Liquids</title>
+          <updated>2017-04-07T05:44:22Z</updated>
+          <author>
+            <name />
+          </author>
+          <link rel="edit" title="Supplier" href="Suppliers(0)" />
+          <link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/Products" type="application/atom+xml;type=feed" title="Products" href="Suppliers(0)/Products" />
+          <category term="ODataDemo.Supplier" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+          <content type="application/xml">
+            <m:properties>
+              <d:ID m:type="Edm.Int32">0</d:ID>
+              <d:Name>Exotic Liquids</d:Name>
+              <d:Concurrency m:type="Edm.Int32">0</d:Concurrency>
+              <d:Address m:type="ODataDemo.Address">
+                <d:Street>NE 228th</d:Street>
+                <d:City>Sammamish</d:City>
+                <d:State>WA</d:State>
+                <d:ZipCode>98074</d:ZipCode>
+                <d:Country>USA</d:Country>
+              </d:Address>
+            </m:properties>
+          </content>
+        </entry>
+      </m:inline>
+    </link>
+    <category term="ODataDemo.Product" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+    <content type="application/xml">
+      <m:properties>
+        <d:ID m:type="Edm.Int32">4</d:ID>
+        <d:ReleaseDate m:type="Edm.DateTime">2003-01-05T00:00:00</d:ReleaseDate>
+        <d:DiscontinuedDate m:type="Edm.DateTime" m:null="true" />
+        <d:Rating m:type="Edm.Int32">3</d:Rating>
+        <d:Price m:type="Edm.Decimal">22.99</d:Price>
+      </m:properties>
+    </content>
+  </entry>
+  <entry>
+    <id>http://services.odata.org/(S(tcjpjrwvrq5cbwf1yqulu1hc))/V2/OData/OData.svc/Products(5)</id>
+    <title type="text">Cranberry Juice</title>
+    <summary type="text">16-Ounce Plastic Bottles (Pack of 12)</summary>
+    <updated>2017-04-07T05:44:22Z</updated>
+    <author>
+      <name />
+    </author>
+    <link rel="edit" title="Product" href="Products(5)" />
+    <link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/Category" type="application/atom+xml;type=entry" title="Category" href="Products(5)/Category" />
+    <link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/Supplier" type="application/atom+xml;type=entry" title="Supplier" href="Products(5)/Supplier">
+      <m:inline>
+        <entry m:etag="W/&quot;0&quot;">
+          <id>http://services.odata.org/(S(tcjpjrwvrq5cbwf1yqulu1hc))/V2/OData/OData.svc/Suppliers(0)</id>
+          <title type="text">Exotic Liquids</title>
+          <updated>2017-04-07T05:44:22Z</updated>
+          <author>
+            <name />
+          </author>
+          <link rel="edit" title="Supplier" href="Suppliers(0)" />
+          <link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/Products" type="application/atom+xml;type=feed" title="Products" href="Suppliers(0)/Products" />
+          <category term="ODataDemo.Supplier" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+          <content type="application/xml">
+            <m:properties>
+              <d:ID m:type="Edm.Int32">0</d:ID>
+              <d:Name>Exotic Liquids</d:Name>
+              <d:Concurrency m:type="Edm.Int32">0</d:Concurrency>
+              <d:Address m:type="ODataDemo.Address">
+                <d:Street>NE 228th</d:Street>
+                <d:City>Sammamish</d:City>
+                <d:State>WA</d:State>
+                <d:ZipCode>98074</d:ZipCode>
+                <d:Country>USA</d:Country>
+              </d:Address>
+            </m:properties>
+          </content>
+        </entry>
+      </m:inline>
+    </link>
+    <category term="ODataDemo.Product" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+    <content type="application/xml">
+      <m:properties>
+        <d:ID m:type="Edm.Int32">5</d:ID>
+        <d:ReleaseDate m:type="Edm.DateTime">2006-08-04T00:00:00</d:ReleaseDate>
+        <d:DiscontinuedDate m:type="Edm.DateTime" m:null="true" />
+        <d:Rating m:type="Edm.Int32">3</d:Rating>
+        <d:Price m:type="Edm.Decimal">22.8</d:Price>
+      </m:properties>
+    </content>
+  </entry>
+  <entry>
+    <id>http://services.odata.org/(S(tcjpjrwvrq5cbwf1yqulu1hc))/V2/OData/OData.svc/Products(6)</id>
+    <title type="text">Pink Lemonade</title>
+    <summary type="text">36 Ounce Cans (Pack of 3)</summary>
+    <updated>2017-04-07T05:44:22Z</updated>
+    <author>
+      <name />
+    </author>
+    <link rel="edit" title="Product" href="Products(6)" />
+    <link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/Category" type="application/atom+xml;type=entry" title="Category" href="Products(6)/Category" />
+    <link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/Supplier" type="application/atom+xml;type=entry" title="Supplier" href="Products(6)/Supplier">
+      <m:inline>
+        <entry m:etag="W/&quot;0&quot;">
+          <id>http://services.odata.org/(S(tcjpjrwvrq5cbwf1yqulu1hc))/V2/OData/OData.svc/Suppliers(0)</id>
+          <title type="text">Exotic Liquids</title>
+          <updated>2017-04-07T05:44:22Z</updated>
+          <author>
+            <name />
+          </author>
+          <link rel="edit" title="Supplier" href="Suppliers(0)" />
+          <link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/Products" type="application/atom+xml;type=feed" title="Products" href="Suppliers(0)/Products" />
+          <category term="ODataDemo.Supplier" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+          <content type="application/xml">
+            <m:properties>
+              <d:ID m:type="Edm.Int32">0</d:ID>
+              <d:Name>Exotic Liquids</d:Name>
+              <d:Concurrency m:type="Edm.Int32">0</d:Concurrency>
+              <d:Address m:type="ODataDemo.Address">
+                <d:Street>NE 228th</d:Street>
+                <d:City>Sammamish</d:City>
+                <d:State>WA</d:State>
+                <d:ZipCode>98074</d:ZipCode>
+                <d:Country>USA</d:Country>
+              </d:Address>
+            </m:properties>
+          </content>
+        </entry>
+      </m:inline>
+    </link>
+    <category term="ODataDemo.Product" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+    <content type="application/xml">
+      <m:properties>
+        <d:ID m:type="Edm.Int32">6</d:ID>
+        <d:ReleaseDate m:type="Edm.DateTime">2006-11-05T00:00:00</d:ReleaseDate>
+        <d:DiscontinuedDate m:type="Edm.DateTime" m:null="true" />
+        <d:Rating m:type="Edm.Int32">3</d:Rating>
+        <d:Price m:type="Edm.Decimal">18.8</d:Price>
+      </m:properties>
+    </content>
+  </entry>
+  <entry>
+    <id>http://services.odata.org/(S(tcjpjrwvrq5cbwf1yqulu1hc))/V2/OData/OData.svc/Products(7)</id>
+    <title type="text">DVD Player</title>
+    <summary type="text">1080P Upconversion DVD Player</summary>
+    <updated>2017-04-07T05:44:22Z</updated>
+    <author>
+      <name />
+    </author>
+    <link rel="edit" title="Product" href="Products(7)" />
+    <link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/Category" type="application/atom+xml;type=entry" title="Category" href="Products(7)/Category" />
+    <link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/Supplier" type="application/atom+xml;type=entry" title="Supplier" href="Products(7)/Supplier">
+      <m:inline>
+        <entry m:etag="W/&quot;0&quot;">
+          <id>http://services.odata.org/(S(tcjpjrwvrq5cbwf1yqulu1hc))/V2/OData/OData.svc/Suppliers(1)</id>
+          <title type="text">Tokyo Traders</title>
+          <updated>2017-04-07T05:44:22Z</updated>
+          <author>
+            <name />
+          </author>
+          <link rel="edit" title="Supplier" href="Suppliers(1)" />
+          <link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/Products" type="application/atom+xml;type=feed" title="Products" href="Suppliers(1)/Products" />
+          <category term="ODataDemo.Supplier" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+          <content type="application/xml">
+            <m:properties>
+              <d:ID m:type="Edm.Int32">1</d:ID>
+              <d:Name>Tokyo Traders</d:Name>
+              <d:Concurrency m:type="Edm.Int32">0</d:Concurrency>
+              <d:Address m:type="ODataDemo.Address">
+                <d:Street>NE 40th</d:Street>
+                <d:City>Redmond</d:City>
+                <d:State>WA</d:State>
+                <d:ZipCode>98052</d:ZipCode>
+                <d:Country>USA</d:Country>
+              </d:Address>
+            </m:properties>
+          </content>
+        </entry>
+      </m:inline>
+    </link>
+    <category term="ODataDemo.Product" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+    <content type="application/xml">
+      <m:properties>
+        <d:ID m:type="Edm.Int32">7</d:ID>
+        <d:ReleaseDate m:type="Edm.DateTime">2006-11-15T00:00:00</d:ReleaseDate>
+        <d:DiscontinuedDate m:type="Edm.DateTime" m:null="true" />
+        <d:Rating m:type="Edm.Int32">3</d:Rating>
+        <d:Price m:type="Edm.Decimal">35.88</d:Price>
+      </m:properties>
+    </content>
+  </entry>
+  <entry>
+    <id>http://services.odata.org/(S(tcjpjrwvrq5cbwf1yqulu1hc))/V2/OData/OData.svc/Products(8)</id>
+    <title type="text">LCD HDTV</title>
+    <summary type="text">42 inch 1080p LCD with Built-in Blu-ray Disc Player</summary>
+    <updated>2017-04-07T05:44:22Z</updated>
+    <author>
+      <name />
+    </author>
+    <link rel="edit" title="Product" href="Products(8)" />
+    <link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/Category" type="application/atom+xml;type=entry" title="Category" href="Products(8)/Category" />
+    <link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/Supplier" type="application/atom+xml;type=entry" title="Supplier" href="Products(8)/Supplier">
+      <m:inline>
+        <entry m:etag="W/&quot;0&quot;">
+          <id>http://services.odata.org/(S(tcjpjrwvrq5cbwf1yqulu1hc))/V2/OData/OData.svc/Suppliers(1)</id>
+          <title type="text">Tokyo Traders</title>
+          <updated>2017-04-07T05:44:22Z</updated>
+          <author>
+            <name />
+          </author>
+          <link rel="edit" title="Supplier" href="Suppliers(1)" />
+          <link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/Products" type="application/atom+xml;type=feed" title="Products" href="Suppliers(1)/Products" />
+          <category term="ODataDemo.Supplier" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+          <content type="application/xml">
+            <m:properties>
+              <d:ID m:type="Edm.Int32">1</d:ID>
+              <d:Name>Tokyo Traders</d:Name>
+              <d:Concurrency m:type="Edm.Int32">0</d:Concurrency>
+              <d:Address m:type="ODataDemo.Address">
+                <d:Street>NE 40th</d:Street>
+                <d:City>Redmond</d:City>
+                <d:State>WA</d:State>
+                <d:ZipCode>98052</d:ZipCode>
+                <d:Country>USA</d:Country>
+              </d:Address>
+            </m:properties>
+          </content>
+        </entry>
+      </m:inline>
+    </link>
+    <category term="ODataDemo.Product" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+    <content type="application/xml">
+      <m:properties>
+        <d:ID m:type="Edm.Int32">8</d:ID>
+        <d:ReleaseDate m:type="Edm.DateTime">2008-05-08T00:00:00</d:ReleaseDate>
+        <d:DiscontinuedDate m:type="Edm.DateTime" m:null="true" />
+        <d:Rating m:type="Edm.Int32">3</d:Rating>
+        <d:Price m:type="Edm.Decimal">1088.8</d:Price>
+      </m:properties>
+    </content>
+  </entry>
+</feed>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/resources/RoomContentOnly.xml
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/resources/RoomContentOnly.xml b/odata2-lib/odata-client-core/src/test/resources/RoomContentOnly.xml
new file mode 100644
index 0000000..558e713
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/resources/RoomContentOnly.xml
@@ -0,0 +1,28 @@
+<!--
+  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.
+-->
+<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://host:8080/ReferenceScenario.svc/" m:etag="W/&quot;1&quot;">
+	<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>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/resources/RoomContentOnlyWithNavigationLink.xml
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/resources/RoomContentOnlyWithNavigationLink.xml b/odata2-lib/odata-client-core/src/test/resources/RoomContentOnlyWithNavigationLink.xml
new file mode 100644
index 0000000..a7d039e
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/resources/RoomContentOnlyWithNavigationLink.xml
@@ -0,0 +1,29 @@
+<!--
+  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.
+-->
+<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://host:8080/ReferenceScenario.svc/" m:etag="W/&quot;1&quot;">
+	<link href="Buildings('1')" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/nr_Building" title="nr_Building" type="application/atom+xml;type=entry"/>
+	<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>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/resources/RoomsToEmployeesWithInlineTeams.xml
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/resources/RoomsToEmployeesWithInlineTeams.xml b/odata2-lib/odata-client-core/src/test/resources/RoomsToEmployeesWithInlineTeams.xml
new file mode 100644
index 0000000..898ce9e
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/resources/RoomsToEmployeesWithInlineTeams.xml
@@ -0,0 +1,104 @@
+<?xml version='1.0' encoding='utf-8'?>
+<feed 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:8083/olingo-odata2-ref-web/ReferenceScenario.svc/">
+	<id>http://localhost:8083/olingo-odata2-ref-web/ReferenceScenario.svc/Employees</id>
+	<title type="text">Employees</title>
+	<updated>2016-11-22T14:21:03.492+05:30</updated>
+	<author>
+		<name/>
+	</author>
+	<link href="Employees" rel="self" title="Employees"/>
+	<entry>
+		<id>http://localhost:8083/olingo-odata2-ref-web/ReferenceScenario.svc/Employees('2')</id>
+		<title type="text">Frederic Fall</title>
+		<updated>2003-07-01T00:00:00Z</updated>
+		<category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+		<link href="Employees('2')" rel="edit" title="Employee"/>
+		<link href="Employees('2')/$value" rel="edit-media" type="image/jpeg"/>
+		<link href="Employees('2')/ne_Manager" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager" title="ne_Manager" type="application/atom+xml;type=entry"/>
+		<link href="Employees('2')/ne_Team" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team" title="ne_Team" type="application/atom+xml;type=entry">
+			<m:inline>
+				<entry xml:base="http://localhost:8083/olingo-odata2-ref-web/ReferenceScenario.svc/">
+					<id>http://localhost:8083/olingo-odata2-ref-web/ReferenceScenario.svc/Teams('1')</id>
+					<title type="text">Team 1</title>
+					<updated>2016-11-22T14:21:03.493+05:30</updated>
+					<category term="RefScenario.Team" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+					<link href="Teams('1')" rel="edit" title="Team"/>
+					<link href="Teams('1')/nt_Employees" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/nt_Employees" title="nt_Employees" type="application/atom+xml;type=feed"/>
+					<content type="application/xml">
+						<m:properties>
+							<d:Id>1</d:Id>
+							<d:Name>Team 1</d:Name>
+							<d:isScrumTeam>false</d:isScrumTeam>
+						</m:properties>
+					</content>
+				</entry>
+			</m:inline>
+		</link>
+		<link href="Employees('2')/ne_Room" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room" title="ne_Room" type="application/atom+xml;type=entry"/>
+		<content type="image/jpeg" src="Employees('2')/$value"/>
+		<m:properties>
+			<d:EmployeeId>2</d:EmployeeId>
+			<d:EmployeeName>Frederic Fall</d:EmployeeName>
+			<d:ManagerId>1</d:ManagerId>
+			<d:RoomId>2</d:RoomId>
+			<d:TeamId>1</d:TeamId>
+			<d:Location m:type="RefScenario.c_Location">
+				<d:City m:type="RefScenario.c_City">
+					<d:PostalCode>69190</d:PostalCode>
+					<d:CityName>Walldorf</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>32</d:Age>
+			<d:EntryDate>2003-07-01T00:00:00</d:EntryDate>
+			<d:ImageUrl>Employees('2')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+	<entry>
+		<id>http://localhost:8083/olingo-odata2-ref-web/ReferenceScenario.svc/Employees('3')</id>
+		<title type="text">Jonathan Smith</title>
+		<updated>2016-11-22T14:21:03.493+05:30</updated>
+		<category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+		<link href="Employees('3')" rel="edit" title="Employee"/>
+		<link href="Employees('3')/$value" rel="edit-media" type="image/jpeg"/>
+		<link href="Employees('3')/ne_Manager" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager" title="ne_Manager" type="application/atom+xml;type=entry"/>
+		<link href="Employees('3')/ne_Team" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team" title="ne_Team" type="application/atom+xml;type=entry">
+			<m:inline>
+				<entry xml:base="http://localhost:8083/olingo-odata2-ref-web/ReferenceScenario.svc/">
+					<id>http://localhost:8083/olingo-odata2-ref-web/ReferenceScenario.svc/Teams('1')</id>
+					<title type="text">Team 1</title>
+					<updated>2016-11-22T14:21:03.494+05:30</updated>
+					<category term="RefScenario.Team" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+					<link href="Teams('1')" rel="edit" title="Team"/>
+					<link href="Teams('1')/nt_Employees" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/nt_Employees" title="nt_Employees" type="application/atom+xml;type=feed"/>
+					<content type="application/xml">
+						<m:properties>
+							<d:Id>1</d:Id>
+							<d:Name>Team 1</d:Name>
+							<d:isScrumTeam>false</d:isScrumTeam>
+						</m:properties>
+					</content>
+				</entry>
+			</m:inline>
+		</link>
+		<link href="Employees('3')/ne_Room" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room" title="ne_Room" type="application/atom+xml;type=entry"/>
+		<content type="image/jpeg" src="Employees('3')/$value"/>
+		<m:properties>
+			<d:EmployeeId>3</d:EmployeeId>
+			<d:EmployeeName>Jonathan Smith</d:EmployeeName>
+			<d:ManagerId>1</d:ManagerId>
+			<d:RoomId>2</d:RoomId>
+			<d:TeamId>1</d:TeamId>
+			<d:Location m:type="RefScenario.c_Location">
+				<d:City m:type="RefScenario.c_City">
+					<d:PostalCode>69190</d:PostalCode>
+					<d:CityName>Walldorf</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>56</d:Age>
+			<d:EntryDate m:null="true"/>
+			<d:ImageUrl>Employees('3')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+</feed>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/resources/batchWithPost.batch
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/resources/batchWithPost.batch b/odata2-lib/odata-client-core/src/test/resources/batchWithPost.batch
new file mode 100644
index 0000000..b7038e9
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/resources/batchWithPost.batch
@@ -0,0 +1,39 @@
+--batch_8194-cf13-1f56
+Content-Type: application/http
+Content-Transfer-Encoding: binary
+
+GET http://localhost/odata/Employees('2')/EmployeeName?$format=json HTTP/1.1
+Accept: application/atomsvc+xml;q=0.8, application/json;odata=verbose;q=0.5, */*;q=0.1
+Accept-Language:en-US,en;q=0.7,en-UK;q=0.9
+MaxDataServiceVersion: 2.0
+
+
+--batch_8194-cf13-1f56
+Content-Type: multipart/mixed; boundary=changeset_f980-1cb6-94dd
+
+--changeset_f980-1cb6-94dd
+Content-Type: application/http
+Content-Transfer-Encoding: binary
+Content-ID: changeRequest1
+
+PUT Employees('2')/EmployeeName HTTP/1.1
+Content-Length: 100000
+Accept: application/atomsvc+xml;q=0.8, application/json;odata=verbose;q=0.5, */*;q=0.1
+DataServiceVersion: 1.0
+Content-Type: application/json;odata=verbose
+MaxDataServiceVersion: 2.0
+
+{"EmployeeName":"Frederic Fall MODIFIED"}
+
+--changeset_f980-1cb6-94dd--
+
+--batch_8194-cf13-1f56
+Content-Type: application/http
+Content-Transfer-Encoding: binary
+
+GET Employees('2')/EmployeeName?$format=json HTTP/1.1
+Accept: application/atomsvc+xml;q=0.8, application/json;odata=verbose;q=0.5, */*;q=0.1
+MaxDataServiceVersion: 2.0
+
+
+--batch_8194-cf13-1f56--

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/resources/double_expanded_team.xml
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/resources/double_expanded_team.xml b/odata2-lib/odata-client-core/src/test/resources/double_expanded_team.xml
new file mode 100644
index 0000000..7a82144
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/resources/double_expanded_team.xml
@@ -0,0 +1,264 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  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.
+-->
+<entry xml:base="http://some.host.com/service.root/"
+	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://some.host.com/service.root/Teams('1')</id>
+	<title type="text">Team 1</title>
+	<updated>2013-03-21T12:44:28Z</updated>
+	<category term="RefScenario.Team"
+		scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+	<link href="Teams('1')" rel="edit" title="Team" />
+	<link href="Teams('1')/nt_Employees"
+		rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/nt_Employees"
+		type="application/atom+xml;type=feed" title="nt_Employees">
+		<m:inline>
+			<feed xml:base="http://some.host.com/service.root/">
+				<id>http://some.host.com/service.root/Employees</id>
+				<title type="text">Employees</title>
+				<updated>2013-03-21T12:44:28Z</updated>
+				<author>
+					<name />
+				</author>
+				<link href="Employees" rel="self" title="Employees" />
+				<entry>
+					<id>http://some.host.com/service.root/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="image/jpeg" />
+					<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">
+						<m:inline>
+							<entry xml:base="http://some.host.com/service.root/">
+								<id>http://some.host.com/service.root/Teams('1')
+								</id>
+								<title type="text">Team 1</title>
+								<updated>2013-03-21T12:44:28Z</updated>
+								<category term="RefScenario.Team"
+									scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+								<link href="Teams('1')" rel="edit" title="Team" />
+								<link href="Teams('1')/nt_Employees"
+									rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/nt_Employees"
+									type="application/atom+xml;type=feed" title="nt_Employees" />
+								<link href="Teams('1')/$links/nt_Employees"
+									rel="http://schemas.microsoft.com/ado/2007/08/dataservices/relatedlinks/nt_Employees"
+									type="application/xml" title="nt_Employees" />
+								<content type="application/xml">
+									<m:properties>
+										<d:Id>1</d:Id>
+										<d:Name>Team 1</d:Name>
+										<d:isScrumTeam>false</d:isScrumTeam>
+									</m:properties>
+								</content>
+							</entry>
+						</m:inline>
+					</link>
+					<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')/$links/ne_Manager"
+						rel="http://schemas.microsoft.com/ado/2007/08/dataservices/relatedlinks/ne_Manager"
+						type="application/xml" title="ne_Manager" />
+					<link href="Employees('1')/$links/ne_Team"
+						rel="http://schemas.microsoft.com/ado/2007/08/dataservices/relatedlinks/ne_Team"
+						type="application/xml" title="ne_Team" />
+					<link href="Employees('1')/$links/ne_Room"
+						rel="http://schemas.microsoft.com/ado/2007/08/dataservices/relatedlinks/ne_Room"
+						type="application/xml" title="ne_Room" />
+					<content type="image/jpeg" 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:City m:type="RefScenario.c_City">
+								<d:PostalCode>69124</d:PostalCode>
+								<d:CityName>Heidelberg</d:CityName>
+							</d:City>
+							<d:Country>Germany</d:Country>
+						</d:Location>
+						<d:Age>52</d:Age>
+						<d:EntryDate>1999-01-01T00:00:00</d:EntryDate>
+						<d:ImageUrl>Employees('1')/$value</d:ImageUrl>
+					</m:properties>
+				</entry>
+				<entry>
+					<id>http://some.host.com/service.root/Employees('2')</id>
+					<title type="text">Frederic Fall</title>
+					<updated>2003-07-01T00:00:00Z</updated>
+					<category term="RefScenario.Employee"
+						scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+					<link href="Employees('2')" rel="edit" title="Employee" />
+					<link href="Employees('2')/$value" rel="edit-media" type="image/jpeg" />
+					<link href="Employees('2')/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('2')/ne_Team"
+						rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team"
+						type="application/atom+xml;type=entry" title="ne_Team">
+						<m:inline>
+							<entry xml:base="http://some.host.com/service.root/">
+								<id>http://some.host.com/service.root/Teams('1')</id>
+								<title type="text">Team 1</title>
+								<updated>2013-03-21T12:44:28Z</updated>
+								<category term="RefScenario.Team"
+									scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+								<link href="Teams('1')" rel="edit" title="Team" />
+								<link href="Teams('1')/nt_Employees"
+									rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/nt_Employees"
+									type="application/atom+xml;type=feed" title="nt_Employees" />
+								<link href="Teams('1')/$links/nt_Employees"
+									rel="http://schemas.microsoft.com/ado/2007/08/dataservices/relatedlinks/nt_Employees"
+									type="application/xml" title="nt_Employees" />
+								<content type="application/xml">
+									<m:properties>
+										<d:Id>1</d:Id>
+										<d:Name>Team 1</d:Name>
+										<d:isScrumTeam>false</d:isScrumTeam>
+									</m:properties>
+								</content>
+							</entry>
+						</m:inline>
+					</link>
+					<link href="Employees('2')/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('2')/$links/ne_Manager"
+						rel="http://schemas.microsoft.com/ado/2007/08/dataservices/relatedlinks/ne_Manager"
+						type="application/xml" title="ne_Manager" />
+					<link href="Employees('2')/$links/ne_Team"
+						rel="http://schemas.microsoft.com/ado/2007/08/dataservices/relatedlinks/ne_Team"
+						type="application/xml" title="ne_Team" />
+					<link href="Employees('2')/$links/ne_Room"
+						rel="http://schemas.microsoft.com/ado/2007/08/dataservices/relatedlinks/ne_Room"
+						type="application/xml" title="ne_Room" />
+					<content type="image/jpeg" src="Employees('2')/$value" />
+					<m:properties>
+						<d:EmployeeId>2</d:EmployeeId>
+						<d:EmployeeName>Frederic Fall</d:EmployeeName>
+						<d:ManagerId>1</d:ManagerId>
+						<d:RoomId>2</d:RoomId>
+						<d:TeamId>1</d:TeamId>
+						<d:Location m:type="RefScenario.c_Location">
+							<d:City m:type="RefScenario.c_City">
+								<d:PostalCode>69190</d:PostalCode>
+								<d:CityName>Walldorf</d:CityName>
+							</d:City>
+							<d:Country>Germany</d:Country>
+						</d:Location>
+						<d:Age>32</d:Age>
+						<d:EntryDate>2003-07-01T00:00:00</d:EntryDate>
+						<d:ImageUrl>Employees('2')/$value</d:ImageUrl>
+					</m:properties>
+				</entry>
+				<entry>
+					<id>http://some.host.com/service.root/Employees('3')</id>
+					<title type="text">Jonathan Smith</title>
+					<updated>2013-03-21T12:44:28Z</updated>
+					<category term="RefScenario.Employee"
+						scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+					<link href="Employees('3')" rel="edit" title="Employee" />
+					<link href="Employees('3')/$value" rel="edit-media" type="image/jpeg" />
+					<link href="Employees('3')/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('3')/ne_Team"
+						rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team"
+						type="application/atom+xml;type=entry" title="ne_Team">
+						<m:inline>
+							<entry xml:base="http://some.host.com/service.root/">
+								<id>http://some.host.com/service.root/Teams('1')</id>
+								<title type="text">Team 1</title>
+								<updated>2013-03-21T12:44:28Z</updated>
+								<category term="RefScenario.Team"
+									scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+								<link href="Teams('1')" rel="edit" title="Team" />
+								<link href="Teams('1')/nt_Employees"
+									rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/nt_Employees"
+									type="application/atom+xml;type=feed" title="nt_Employees" />
+								<link href="Teams('1')/$links/nt_Employees"
+									rel="http://schemas.microsoft.com/ado/2007/08/dataservices/relatedlinks/nt_Employees"
+									type="application/xml" title="nt_Employees" />
+								<content type="application/xml">
+									<m:properties>
+										<d:Id>1</d:Id>
+										<d:Name>Team 1</d:Name>
+										<d:isScrumTeam>false</d:isScrumTeam>
+									</m:properties>
+								</content>
+							</entry>
+						</m:inline>
+					</link>
+					<link href="Employees('3')/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('3')/$links/ne_Manager"
+						rel="http://schemas.microsoft.com/ado/2007/08/dataservices/relatedlinks/ne_Manager"
+						type="application/xml" title="ne_Manager" />
+					<link href="Employees('3')/$links/ne_Team"
+						rel="http://schemas.microsoft.com/ado/2007/08/dataservices/relatedlinks/ne_Team"
+						type="application/xml" title="ne_Team" />
+					<link href="Employees('3')/$links/ne_Room"
+						rel="http://schemas.microsoft.com/ado/2007/08/dataservices/relatedlinks/ne_Room"
+						type="application/xml" title="ne_Room" />
+					<content type="image/jpeg" src="Employees('3')/$value" />
+					<m:properties>
+						<d:EmployeeId>3</d:EmployeeId>
+						<d:EmployeeName>Jonathan Smith</d:EmployeeName>
+						<d:ManagerId>1</d:ManagerId>
+						<d:RoomId>2</d:RoomId>
+						<d:TeamId>1</d:TeamId>
+						<d:Location m:type="RefScenario.c_Location">
+							<d:City m:type="RefScenario.c_City">
+								<d:PostalCode>69190</d:PostalCode>
+								<d:CityName>Walldorf</d:CityName>
+							</d:City>
+							<d:Country>Germany</d:Country>
+						</d:Location>
+						<d:Age>56</d:Age>
+						<d:EntryDate m:null="true" />
+						<d:ImageUrl>Employees('3')/$value</d:ImageUrl>
+					</m:properties>
+				</entry>
+			</feed>
+		</m:inline>
+	</link>
+	<link href="Teams('1')/$links/nt_Employees"
+		rel="http://schemas.microsoft.com/ado/2007/08/dataservices/relatedlinks/nt_Employees"
+		type="application/xml" title="nt_Employees" />
+	<content type="application/xml">
+		<m:properties>
+			<d:Id>1</d:Id>
+			<d:Name>Team 1</d:Name>
+			<d:isScrumTeam>false</d:isScrumTeam>
+		</m:properties>
+	</content>
+</entry>

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/resources/expandedBuilding.xml
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/resources/expandedBuilding.xml b/odata2-lib/odata-client-core/src/test/resources/expandedBuilding.xml
new file mode 100644
index 0000000..e637969
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/resources/expandedBuilding.xml
@@ -0,0 +1,61 @@
+<?xml version='1.0' encoding='utf-8'?>
+<!--
+    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.
+-->
+<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://some.host.com/service.root/ReferenceScenario.svc/">
+    <id>http://some.host.com/service.root/ReferenceScenario.svc/Rooms('1')</id>
+    <title type="text">Room 1</title>
+    <updated>2013-04-19T10:58:03.646Z</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"
+        title="nr_Employees" type="application/atom+xml; type=feed" />
+    <link href="Rooms('1')/nr_Building" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/nr_Building"
+        title="nr_Building" type="application/atom+xml; type=entry">
+        <m:inline>
+            <entry>
+                <id>http://some.host.com/service.root/ReferenceScenario.svc/Buildings('1')</id>
+                <title type="text">Buildings</title>
+                <updated>2013-04-19T10:58:03.646Z</updated>
+                <author>
+                    <name>Building 1</name>
+                </author>
+                <category term="RefScenario.Building" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+                <link href="Buildings('1')" rel="edit" title="Building" />
+                <link href="Buildings('1')/nb_Rooms" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/nb_Rooms"
+                    title="nb_Rooms" type="application/atom+xml; type=feed" />
+                <content type="application/xml">
+                    <m:properties>
+                        <d:Id>1</d:Id>
+                        <d:Name>Building 1</d:Name>
+                        <d:Image m:null="true" />
+                    </m:properties>
+                </content>
+            </entry>
+        </m:inline>
+    </link>
+    <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>

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/resources/expanded_team.xml
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/resources/expanded_team.xml b/odata2-lib/odata-client-core/src/test/resources/expanded_team.xml
new file mode 100644
index 0000000..c18a78b
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/resources/expanded_team.xml
@@ -0,0 +1,146 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  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.
+-->
+<entry xml:base="http://some.host.com/service.root/"
+       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://some.host.com/service.root/Teams('1')</id>
+    <title type="text">Team 1</title>
+    <updated>2013-03-14T11:16:48Z</updated>
+    <category term="RefScenario.Team" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+    <link href="Teams('1')" rel="edit" title="Team"/>
+    <link href="Teams('1')/nt_Employees" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/nt_Employees" type="application/atom+xml;type=feed" title="nt_Employees">
+        <m:inline>
+            <feed xml:base="http://some.host.com/service.root/">
+                <id>http://some.host.com/service.root/Employees</id>
+                <title type="text">Employees</title>
+                <updated>2013-03-14T11:16:48Z</updated>
+                <author>
+                    <name/>
+                </author>
+                <link href="Employees" rel="self" title="Employees"/>
+                <entry>
+                    <id>http://some.host.com/service.root/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="image/jpeg"/>
+                    <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"/>
+                    <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')/$links/ne_Manager" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/relatedlinks/ne_Manager" type="application/xml" title="ne_Manager"/>
+                    <link href="Employees('1')/$links/ne_Team" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/relatedlinks/ne_Team" type="application/xml" title="ne_Team"/>
+                    <link href="Employees('1')/$links/ne_Room" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/relatedlinks/ne_Room" type="application/xml" title="ne_Room"/>
+                    <content type="image/jpeg" 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:City m:type="RefScenario.c_City">
+                                <d:PostalCode>69124</d:PostalCode>
+                                <d:CityName>Heidelberg</d:CityName>
+                            </d:City>
+                            <d:Country>Germany</d:Country>
+                        </d:Location>
+                        <d:Age>52</d:Age>
+                        <d:EntryDate>1999-01-01T00:00:00</d:EntryDate>
+                        <d:ImageUrl>Employees('1')/$value</d:ImageUrl>
+                    </m:properties>
+                </entry>
+                <entry>
+                    <id>http://some.host.com/service.root/Employees('2')</id>
+                    <title type="text">Frederic Fall</title>
+                    <updated>2003-07-01T00:00:00Z</updated>
+                    <category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+                    <link href="Employees('2')" rel="edit" title="Employee"/>
+                    <link href="Employees('2')/$value" rel="edit-media" type="image/jpeg"/>
+                    <link href="Employees('2')/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('2')/ne_Team" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team" type="application/atom+xml;type=entry" title="ne_Team"/>
+                    <link href="Employees('2')/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('2')/$links/ne_Manager" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/relatedlinks/ne_Manager" type="application/xml" title="ne_Manager"/>
+                    <link href="Employees('2')/$links/ne_Team" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/relatedlinks/ne_Team" type="application/xml" title="ne_Team"/>
+                    <link href="Employees('2')/$links/ne_Room" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/relatedlinks/ne_Room" type="application/xml" title="ne_Room"/>
+                    <content type="image/jpeg" src="Employees('2')/$value"/>
+                    <m:properties>
+                        <d:EmployeeId>2</d:EmployeeId>
+                        <d:EmployeeName>Frederic Fall</d:EmployeeName>
+                        <d:ManagerId>1</d:ManagerId>
+                        <d:RoomId>2</d:RoomId>
+                        <d:TeamId>1</d:TeamId>
+                        <d:Location m:type="RefScenario.c_Location">
+                            <d:City m:type="RefScenario.c_City">
+                                <d:PostalCode>69190</d:PostalCode>
+                                <d:CityName>Walldorf</d:CityName>
+                            </d:City>
+                            <d:Country>Germany</d:Country>
+                        </d:Location>
+                        <d:Age>32</d:Age>
+                        <d:EntryDate>2003-07-01T00:00:00</d:EntryDate>
+                        <d:ImageUrl>Employees('2')/$value</d:ImageUrl>
+                    </m:properties>
+                </entry>
+                <entry>
+                    <id>http://some.host.com/service.root/Employees('3')</id>
+                    <title type="text">Jonathan Smith</title>
+                    <updated>2013-03-14T11:16:48Z</updated>
+                    <category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+                    <link href="Employees('3')" rel="edit" title="Employee"/>
+                    <link href="Employees('3')/$value" rel="edit-media" type="image/jpeg"/>
+                    <link href="Employees('3')/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('3')/ne_Team" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team" type="application/atom+xml;type=entry" title="ne_Team"/>
+                    <link href="Employees('3')/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('3')/$links/ne_Manager" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/relatedlinks/ne_Manager" type="application/xml" title="ne_Manager"/>
+                    <link href="Employees('3')/$links/ne_Team" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/relatedlinks/ne_Team" type="application/xml" title="ne_Team"/>
+                    <link href="Employees('3')/$links/ne_Room" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/relatedlinks/ne_Room" type="application/xml" title="ne_Room"/>
+                    <content type="image/jpeg" src="Employees('3')/$value"/>
+                    <m:properties>
+                        <d:EmployeeId>3</d:EmployeeId>
+                        <d:EmployeeName>Jonathan Smith</d:EmployeeName>
+                        <d:ManagerId>1</d:ManagerId>
+                        <d:RoomId>2</d:RoomId>
+                        <d:TeamId>1</d:TeamId>
+                        <d:Location m:type="RefScenario.c_Location">
+                            <d:City m:type="RefScenario.c_City">
+                                <d:PostalCode>69190</d:PostalCode>
+                                <d:CityName>Walldorf</d:CityName>
+                            </d:City>
+                            <d:Country>Germany</d:Country>
+                        </d:Location>
+                        <d:Age>56</d:Age>
+                        <d:EntryDate m:null="true"/>
+                        <d:ImageUrl>Employees('3')/$value</d:ImageUrl>
+                    </m:properties>
+                </entry>
+            </feed>
+        </m:inline>
+    </link>
+    <link href="Teams('1')/$links/nt_Employees" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/relatedlinks/nt_Employees" type="application/xml" title="nt_Employees"/>
+    <content type="application/xml">
+        <m:properties>
+            <d:Id>1</d:Id>
+            <d:Name>Team 1</d:Name>
+            <d:isScrumTeam>false</d:isScrumTeam>
+        </m:properties>
+    </content>
+</entry>

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/resources/feed_employees.xml
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/resources/feed_employees.xml b/odata2-lib/odata-client-core/src/test/resources/feed_employees.xml
new file mode 100644
index 0000000..53e124f
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/resources/feed_employees.xml
@@ -0,0 +1,247 @@
+<?xml version='1.0' encoding='utf-8'?>
+<!--
+  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.
+-->
+<feed 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://some.host.com/service.root/ReferenceScenario.svc/">
+	<id>http://some.host.com/service.root/ReferenceScenario.svc/Employees</id>
+	<title type="text">Employees</title>
+	<updated>2013-04-23T11:46:14.926Z</updated>
+	<author>
+		<name />
+	</author>
+	<link href="Employees" rel="self" title="Employees" />
+	<entry>
+		<id>http://some.host.com/service.root/ReferenceScenario.svc/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" />
+		<link href="Employees('1')/ne_Manager"
+			rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager"
+			title="ne_Manager" type="application/atom+xml; type=entry" />
+		<link href="Employees('1')/ne_Team"
+			rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team"
+			title="ne_Team" type="application/atom+xml; type=entry" />
+		<link href="Employees('1')/ne_Room"
+			rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room"
+			title="ne_Room" type="application/atom+xml; type=entry" />
+		<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:City m:type="RefScenario.c_City">
+					<d:PostalCode>69124</d:PostalCode>
+					<d:CityName>Heidelberg</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>52</d:Age>
+			<d:EntryDate>1999-01-01T00:00:00</d:EntryDate>
+			<d:ImageUrl>Employees('1')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+	<entry>
+		<id>http://some.host.com/service.root/ReferenceScenario.svc/Employees('2')</id>
+		<title type="text">Frederic Fall</title>
+		<updated>2003-07-01T00:00:00Z</updated>
+		<category term="RefScenario.Employee"
+			scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+		<link href="Employees('2')" rel="edit" title="Employee" />
+		<link href="Employees('2')/$value" rel="edit-media" type="application/octet-stream" />
+		<link href="Employees('2')/ne_Manager"
+			rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager"
+			title="ne_Manager" type="application/atom+xml; type=entry" />
+		<link href="Employees('2')/ne_Team"
+			rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team"
+			title="ne_Team" type="application/atom+xml; type=entry" />
+		<link href="Employees('2')/ne_Room"
+			rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room"
+			title="ne_Room" type="application/atom+xml; type=entry" />
+		<content type="application/octet-stream" src="Employees('2')/$value" />
+		<m:properties>
+			<d:EmployeeId>2</d:EmployeeId>
+			<d:EmployeeName>Frederic Fall</d:EmployeeName>
+			<d:ManagerId>1</d:ManagerId>
+			<d:RoomId>2</d:RoomId>
+			<d:TeamId>1</d:TeamId>
+			<d:Location m:type="RefScenario.c_Location">
+				<d:City m:type="RefScenario.c_City">
+					<d:PostalCode>69190</d:PostalCode>
+					<d:CityName>Walldorf</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>32</d:Age>
+			<d:EntryDate>2003-07-01T00:00:00</d:EntryDate>
+			<d:ImageUrl>Employees('2')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+	<entry>
+		<id>http://some.host.com/service.root/ReferenceScenario.svc/Employees('3')</id>
+		<title type="text">Jonathan Smith</title>
+		<updated>2013-04-23T11:46:14.928Z</updated>
+		<category term="RefScenario.Employee"
+			scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+		<link href="Employees('3')" rel="edit" title="Employee" />
+		<link href="Employees('3')/$value" rel="edit-media" type="application/octet-stream" />
+		<link href="Employees('3')/ne_Manager"
+			rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager"
+			title="ne_Manager" type="application/atom+xml; type=entry" />
+		<link href="Employees('3')/ne_Team"
+			rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team"
+			title="ne_Team" type="application/atom+xml; type=entry" />
+		<link href="Employees('3')/ne_Room"
+			rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room"
+			title="ne_Room" type="application/atom+xml; type=entry" />
+		<content type="application/octet-stream" src="Employees('3')/$value" />
+		<m:properties>
+			<d:EmployeeId>3</d:EmployeeId>
+			<d:EmployeeName>Jonathan Smith</d:EmployeeName>
+			<d:ManagerId>1</d:ManagerId>
+			<d:RoomId>2</d:RoomId>
+			<d:TeamId>1</d:TeamId>
+			<d:Location m:type="RefScenario.c_Location">
+				<d:City m:type="RefScenario.c_City">
+					<d:PostalCode>69190</d:PostalCode>
+					<d:CityName>Walldorf</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>56</d:Age>
+			<d:EntryDate m:null="true" />
+			<d:ImageUrl>Employees('3')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+	<entry>
+		<id>http://some.host.com/service.root/ReferenceScenario.svc/Employees('4')</id>
+		<title type="text">Peter Burke</title>
+		<updated>2004-09-12T00:00:00Z</updated>
+		<category term="RefScenario.Employee"
+			scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+		<link href="Employees('4')" rel="edit" title="Employee" />
+		<link href="Employees('4')/$value" rel="edit-media" type="application/octet-stream" />
+		<link href="Employees('4')/ne_Manager"
+			rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager"
+			title="ne_Manager" type="application/atom+xml; type=entry" />
+		<link href="Employees('4')/ne_Team"
+			rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team"
+			title="ne_Team" type="application/atom+xml; type=entry" />
+		<link href="Employees('4')/ne_Room"
+			rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room"
+			title="ne_Room" type="application/atom+xml; type=entry" />
+		<content type="application/octet-stream" src="Employees('4')/$value" />
+		<m:properties>
+			<d:EmployeeId>4</d:EmployeeId>
+			<d:EmployeeName>Peter Burke</d:EmployeeName>
+			<d:ManagerId>3</d:ManagerId>
+			<d:RoomId>2</d:RoomId>
+			<d:TeamId>2</d:TeamId>
+			<d:Location m:type="RefScenario.c_Location">
+				<d:City m:type="RefScenario.c_City">
+					<d:PostalCode>69190</d:PostalCode>
+					<d:CityName>Walldorf</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>39</d:Age>
+			<d:EntryDate>2004-09-12T00:00:00</d:EntryDate>
+			<d:ImageUrl>Employees('4')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+	<entry>
+		<id>http://some.host.com/service.root/ReferenceScenario.svc/Employees('5')</id>
+		<title type="text">John Field</title>
+		<updated>2001-02-01T00:00:00Z</updated>
+		<category term="RefScenario.Employee"
+			scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+		<link href="Employees('5')" rel="edit" title="Employee" />
+		<link href="Employees('5')/$value" rel="edit-media" type="application/octet-stream" />
+		<link href="Employees('5')/ne_Manager"
+			rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager"
+			title="ne_Manager" type="application/atom+xml; type=entry" />
+		<link href="Employees('5')/ne_Team"
+			rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team"
+			title="ne_Team" type="application/atom+xml; type=entry" />
+		<link href="Employees('5')/ne_Room"
+			rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room"
+			title="ne_Room" type="application/atom+xml; type=entry" />
+		<content type="application/octet-stream" src="Employees('5')/$value" />
+		<m:properties>
+			<d:EmployeeId>5</d:EmployeeId>
+			<d:EmployeeName>John Field</d:EmployeeName>
+			<d:ManagerId>3</d:ManagerId>
+			<d:RoomId>3</d:RoomId>
+			<d:TeamId>2</d:TeamId>
+			<d:Location m:type="RefScenario.c_Location">
+				<d:City m:type="RefScenario.c_City">
+					<d:PostalCode>69190</d:PostalCode>
+					<d:CityName>Walldorf</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>42</d:Age>
+			<d:EntryDate>2001-02-01T00:00:00</d:EntryDate>
+			<d:ImageUrl>Employees('5')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+	<entry>
+		<id>http://some.host.com/service.root/ReferenceScenario.svc/Employees('6')</id>
+		<title type="text">Susan Bay</title>
+		<updated>2010-12-01T00:00:00Z</updated>
+		<category term="RefScenario.Employee"
+			scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+		<link href="Employees('6')" rel="edit" title="Employee" />
+		<link href="Employees('6')/$value" rel="edit-media" type="application/octet-stream" />
+		<link href="Employees('6')/ne_Manager"
+			rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager"
+			title="ne_Manager" type="application/atom+xml; type=entry" />
+		<link href="Employees('6')/ne_Team"
+			rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team"
+			title="ne_Team" type="application/atom+xml; type=entry" />
+		<link href="Employees('6')/ne_Room"
+			rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room"
+			title="ne_Room" type="application/atom+xml; type=entry" />
+		<content type="application/octet-stream" src="Employees('6')/$value" />
+		<m:properties>
+			<d:EmployeeId>6</d:EmployeeId>
+			<d:EmployeeName>Susan Bay</d:EmployeeName>
+			<d:ManagerId>1</d:ManagerId>
+			<d:RoomId>2</d:RoomId>
+			<d:TeamId>3</d:TeamId>
+			<d:Location m:type="RefScenario.c_Location">
+				<d:City m:type="RefScenario.c_City">
+					<d:PostalCode>69190</d:PostalCode>
+					<d:CityName>Walldorf</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>29</d:Age>
+			<d:EntryDate>2010-12-01T00:00:00</d:EntryDate>
+			<d:ImageUrl>Employees('6')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+</feed>

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/resources/feed_employees_full.xml
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/resources/feed_employees_full.xml b/odata2-lib/odata-client-core/src/test/resources/feed_employees_full.xml
new file mode 100644
index 0000000..fc78f99
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/resources/feed_employees_full.xml
@@ -0,0 +1,249 @@
+<?xml version='1.0' encoding='utf-8'?>
+<!--
+  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.
+-->
+<feed 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://some.host.com/service.root/ReferenceScenario.svc/">
+	<id>http://some.host.com/service.root/ReferenceScenario.svc/Employees</id>
+	<title type="text">Employees</title>
+	<updated>2013-04-23T11:46:14.926Z</updated>
+	<author>
+		<name />
+	</author>
+    <m:count>6</m:count>
+	<link href="Employees" rel="self" title="Employees" />
+    <link href="http://thisisanextlink" rel="next"/>
+	<entry>
+		<id>http://some.host.com/service.root/ReferenceScenario.svc/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" />
+		<link href="Employees('1')/ne_Manager"
+			rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager"
+			title="ne_Manager" type="application/atom+xml; type=entry" />
+		<link href="Employees('1')/ne_Team"
+			rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team"
+			title="ne_Team" type="application/atom+xml; type=entry" />
+		<link href="Employees('1')/ne_Room"
+			rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room"
+			title="ne_Room" type="application/atom+xml; type=entry" />
+		<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:City m:type="RefScenario.c_City">
+					<d:PostalCode>69124</d:PostalCode>
+					<d:CityName>Heidelberg</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>52</d:Age>
+			<d:EntryDate>1999-01-01T00:00:00</d:EntryDate>
+			<d:ImageUrl>Employees('1')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+	<entry>
+		<id>http://some.host.com/service.root/ReferenceScenario.svc/Employees('2')</id>
+		<title type="text">Frederic Fall</title>
+		<updated>2003-07-01T00:00:00Z</updated>
+		<category term="RefScenario.Employee"
+			scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+		<link href="Employees('2')" rel="edit" title="Employee" />
+		<link href="Employees('2')/$value" rel="edit-media" type="application/octet-stream" />
+		<link href="Employees('2')/ne_Manager"
+			rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager"
+			title="ne_Manager" type="application/atom+xml; type=entry" />
+		<link href="Employees('2')/ne_Team"
+			rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team"
+			title="ne_Team" type="application/atom+xml; type=entry" />
+		<link href="Employees('2')/ne_Room"
+			rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room"
+			title="ne_Room" type="application/atom+xml; type=entry" />
+		<content type="application/octet-stream" src="Employees('2')/$value" />
+		<m:properties>
+			<d:EmployeeId>2</d:EmployeeId>
+			<d:EmployeeName>Frederic Fall</d:EmployeeName>
+			<d:ManagerId>1</d:ManagerId>
+			<d:RoomId>2</d:RoomId>
+			<d:TeamId>1</d:TeamId>
+			<d:Location m:type="RefScenario.c_Location">
+				<d:City m:type="RefScenario.c_City">
+					<d:PostalCode>69190</d:PostalCode>
+					<d:CityName>Walldorf</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>32</d:Age>
+			<d:EntryDate>2003-07-01T00:00:00</d:EntryDate>
+			<d:ImageUrl>Employees('2')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+	<entry>
+		<id>http://some.host.com/service.root/ReferenceScenario.svc/Employees('3')</id>
+		<title type="text">Jonathan Smith</title>
+		<updated>2013-04-23T11:46:14.928Z</updated>
+		<category term="RefScenario.Employee"
+			scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+		<link href="Employees('3')" rel="edit" title="Employee" />
+		<link href="Employees('3')/$value" rel="edit-media" type="application/octet-stream" />
+		<link href="Employees('3')/ne_Manager"
+			rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager"
+			title="ne_Manager" type="application/atom+xml; type=entry" />
+		<link href="Employees('3')/ne_Team"
+			rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team"
+			title="ne_Team" type="application/atom+xml; type=entry" />
+		<link href="Employees('3')/ne_Room"
+			rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room"
+			title="ne_Room" type="application/atom+xml; type=entry" />
+		<content type="application/octet-stream" src="Employees('3')/$value" />
+		<m:properties>
+			<d:EmployeeId>3</d:EmployeeId>
+			<d:EmployeeName>Jonathan Smith</d:EmployeeName>
+			<d:ManagerId>1</d:ManagerId>
+			<d:RoomId>2</d:RoomId>
+			<d:TeamId>1</d:TeamId>
+			<d:Location m:type="RefScenario.c_Location">
+				<d:City m:type="RefScenario.c_City">
+					<d:PostalCode>69190</d:PostalCode>
+					<d:CityName>Walldorf</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>56</d:Age>
+			<d:EntryDate m:null="true" />
+			<d:ImageUrl>Employees('3')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+	<entry>
+		<id>http://some.host.com/service.root/ReferenceScenario.svc/Employees('4')</id>
+		<title type="text">Peter Burke</title>
+		<updated>2004-09-12T00:00:00Z</updated>
+		<category term="RefScenario.Employee"
+			scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+		<link href="Employees('4')" rel="edit" title="Employee" />
+		<link href="Employees('4')/$value" rel="edit-media" type="application/octet-stream" />
+		<link href="Employees('4')/ne_Manager"
+			rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager"
+			title="ne_Manager" type="application/atom+xml; type=entry" />
+		<link href="Employees('4')/ne_Team"
+			rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team"
+			title="ne_Team" type="application/atom+xml; type=entry" />
+		<link href="Employees('4')/ne_Room"
+			rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room"
+			title="ne_Room" type="application/atom+xml; type=entry" />
+		<content type="application/octet-stream" src="Employees('4')/$value" />
+		<m:properties>
+			<d:EmployeeId>4</d:EmployeeId>
+			<d:EmployeeName>Peter Burke</d:EmployeeName>
+			<d:ManagerId>3</d:ManagerId>
+			<d:RoomId>2</d:RoomId>
+			<d:TeamId>2</d:TeamId>
+			<d:Location m:type="RefScenario.c_Location">
+				<d:City m:type="RefScenario.c_City">
+					<d:PostalCode>69190</d:PostalCode>
+					<d:CityName>Walldorf</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>39</d:Age>
+			<d:EntryDate>2004-09-12T00:00:00</d:EntryDate>
+			<d:ImageUrl>Employees('4')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+	<entry>
+		<id>http://some.host.com/service.root/ReferenceScenario.svc/Employees('5')</id>
+		<title type="text">John Field</title>
+		<updated>2001-02-01T00:00:00Z</updated>
+		<category term="RefScenario.Employee"
+			scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+		<link href="Employees('5')" rel="edit" title="Employee" />
+		<link href="Employees('5')/$value" rel="edit-media" type="application/octet-stream" />
+		<link href="Employees('5')/ne_Manager"
+			rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager"
+			title="ne_Manager" type="application/atom+xml; type=entry" />
+		<link href="Employees('5')/ne_Team"
+			rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team"
+			title="ne_Team" type="application/atom+xml; type=entry" />
+		<link href="Employees('5')/ne_Room"
+			rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room"
+			title="ne_Room" type="application/atom+xml; type=entry" />
+		<content type="application/octet-stream" src="Employees('5')/$value" />
+		<m:properties>
+			<d:EmployeeId>5</d:EmployeeId>
+			<d:EmployeeName>John Field</d:EmployeeName>
+			<d:ManagerId>3</d:ManagerId>
+			<d:RoomId>3</d:RoomId>
+			<d:TeamId>2</d:TeamId>
+			<d:Location m:type="RefScenario.c_Location">
+				<d:City m:type="RefScenario.c_City">
+					<d:PostalCode>69190</d:PostalCode>
+					<d:CityName>Walldorf</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>42</d:Age>
+			<d:EntryDate>2001-02-01T00:00:00</d:EntryDate>
+			<d:ImageUrl>Employees('5')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+	<entry>
+		<id>http://some.host.com/service.root/ReferenceScenario.svc/Employees('6')</id>
+		<title type="text">Susan Bay</title>
+		<updated>2010-12-01T00:00:00Z</updated>
+		<category term="RefScenario.Employee"
+			scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+		<link href="Employees('6')" rel="edit" title="Employee" />
+		<link href="Employees('6')/$value" rel="edit-media" type="application/octet-stream" />
+		<link href="Employees('6')/ne_Manager"
+			rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager"
+			title="ne_Manager" type="application/atom+xml; type=entry" />
+		<link href="Employees('6')/ne_Team"
+			rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team"
+			title="ne_Team" type="application/atom+xml; type=entry" />
+		<link href="Employees('6')/ne_Room"
+			rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room"
+			title="ne_Room" type="application/atom+xml; type=entry" />
+		<content type="application/octet-stream" src="Employees('6')/$value" />
+		<m:properties>
+			<d:EmployeeId>6</d:EmployeeId>
+			<d:EmployeeName>Susan Bay</d:EmployeeName>
+			<d:ManagerId>1</d:ManagerId>
+			<d:RoomId>2</d:RoomId>
+			<d:TeamId>3</d:TeamId>
+			<d:Location m:type="RefScenario.c_Location">
+				<d:City m:type="RefScenario.c_City">
+					<d:PostalCode>69190</d:PostalCode>
+					<d:CityName>Walldorf</d:CityName>
+				</d:City>
+				<d:Country>Germany</d:Country>
+			</d:Location>
+			<d:Age>29</d:Age>
+			<d:EntryDate>2010-12-01T00:00:00</d:EntryDate>
+			<d:ImageUrl>Employees('6')/$value</d:ImageUrl>
+		</m:properties>
+	</entry>
+</feed>


[17/24] olingo-odata2 git commit: [OLINGO-1253]Client Module for Olingo v2

Posted by ar...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/uri/EdmURIBuilderImpl.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/uri/EdmURIBuilderImpl.java b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/uri/EdmURIBuilderImpl.java
new file mode 100644
index 0000000..567d3bc
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/uri/EdmURIBuilderImpl.java
@@ -0,0 +1,491 @@
+package org.apache.olingo.odata2.client.core.uri;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmFunctionImport;
+import org.apache.olingo.odata2.api.edm.EdmLiteralKind;
+import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
+import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
+import org.apache.olingo.odata2.api.edm.EdmParameter;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.edm.EdmSimpleType;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeException;
+import org.apache.olingo.odata2.api.edm.EdmTypeKind;
+import org.apache.olingo.odata2.client.api.uri.EdmURIBuilder;
+import org.apache.olingo.odata2.client.api.uri.QueryOption;
+import org.apache.olingo.odata2.client.api.uri.SegmentType;
+import org.apache.olingo.odata2.client.core.uri.util.UriUtil;
+import org.apache.olingo.odata2.core.commons.Encoder;
+
+/**
+ * This is a builder class that constructs URI with edm validations
+ *
+ */
+public class EdmURIBuilderImpl implements EdmURIBuilder{
+  protected final List<Segment> segments = new ArrayList<Segment>();
+  private SegmentType state = SegmentType.INITIAL;
+  
+  /**
+   * Insertion-order map of query options.
+   */
+  protected final Map<String, String> queryOptions = new LinkedHashMap<String, String>();
+  
+  /**
+   * Insertion-order map of custom query options.
+   */
+  protected final Map<String, String> customQueryOptions = new LinkedHashMap<String, String>();
+  
+  /**
+   * Insertion-order map of function import parameters.
+   */
+  protected final Map<String, Object> functionImportParameters = new LinkedHashMap<String, Object>();
+  
+  /**
+   * Constructor.
+   *
+   * @param serviceRoot absolute URL (schema, host and port included) representing the location of the root of the data
+   * service.
+   */
+  public EdmURIBuilderImpl(final String serviceRoot) {
+    state = SegmentType.INITIAL;
+    segments.add(new Segment(SegmentType.INITIAL, serviceRoot));
+  }
+  
+  @Override
+  public EdmURIBuilder appendCountSegment() {
+    switch (state) {
+    case INITIAL:
+    case SIMPLEPROPERTY:
+    case COMPLEXPROPERTY:
+    case NAVIGATION_TO_ONE:
+    case NAVIGATION_TO_MANY_WITH_KEY:
+    case FUNCTIONIMPORT_WITH_KEY:
+    case ENTITY:
+        throw new RuntimeException("Can't specify a key at this position");//NOSONAR
+    case ENTITYSET:
+        appendCount();
+        break;
+    case NAVIGATION_TO_MANY:
+        appendCount();
+        break;
+    case FUNCTIONIMPORT_MANY:
+      appendCount();
+      break;
+    default:
+        throw new RuntimeException("Unkown state:" + state);//NOSONAR
+    }
+    return this;
+  }
+
+  private void appendCount() {
+    segments.add(new Segment(SegmentType.COUNT, SegmentType.COUNT.getValue()));
+    state = SegmentType.COUNT;
+  }
+
+  @Override
+  public EdmURIBuilder appendValueSegment() {
+    switch (state) {
+    case INITIAL:
+    case COMPLEXPROPERTY:
+    case ENTITYSET:
+    case NAVIGATION_TO_MANY:
+    case ENTITY:
+    case NAVIGATION_TO_MANY_WITH_KEY:
+    case NAVIGATION_TO_ONE:
+        throw new RuntimeException("Can't specify a navigation at this position");//NOSONAR
+    case SIMPLEPROPERTY:
+      addValueSegment();
+      break;
+    default:
+        throw new RuntimeException("Unkown state:" + state);//NOSONAR
+    }
+    return this;
+  }
+  
+  private void addValueSegment() {
+    segments.add(new Segment(SegmentType.VALUE, SegmentType.VALUE.getValue()));
+  }
+
+  @Override
+  public EdmURIBuilder appendMetadataSegment() {
+    segments.add(new Segment(SegmentType.METADATA, SegmentType.METADATA.getValue()));
+    return this;
+  }
+
+  @Override
+  public EdmURIBuilder format(String format) { //NOSONAR
+    switch (state) {
+    case INITIAL:
+    case COUNT:
+    case VALUE:
+      throw new RuntimeException("Can't specify a format at this position");//NOSONAR
+    case NAVIGATION_TO_ONE:
+    case SIMPLEPROPERTY:
+    case COMPLEXPROPERTY:
+    case ENTITYSET:
+    case NAVIGATION_TO_MANY:
+    case ENTITY:
+    case NAVIGATION_TO_MANY_WITH_KEY:
+        addFormat(format);
+        break;
+    default:
+        throw new RuntimeException("Unkown state:" + state);//NOSONAR
+    }
+    return this;
+  }
+
+  private void addFormat(String format) {
+    addQueryOption(QueryOption.FORMAT.toString(), format, true);
+  }
+
+  @Override
+  public EdmURIBuilder appendEntitySetSegment(EdmEntitySet entitySet) {
+    state = SegmentType.ENTITYSET;
+    try {
+      segments.add(new Segment(SegmentType.ENTITYSET, entitySet.getName()));
+    } catch (EdmException e) {
+      throw new RuntimeException("Unexpected EDM Exception: ", e);//NOSONAR
+    }
+    return this;
+  }
+
+  @Override
+  public EdmURIBuilder appendNavigationSegment(EdmNavigationProperty property) {
+    switch (state) {
+    case INITIAL:
+    case SIMPLEPROPERTY:
+    case COMPLEXPROPERTY:
+    case ENTITYSET:
+    case NAVIGATION_TO_MANY:
+    case FUNCTIONIMPORT_MANY:
+        throw new RuntimeException("Can't specify a navigation at this position");//NOSONAR
+    case NAVIGATION_TO_ONE:
+        addNavigationSegment(property);
+        break;
+    case ENTITY:
+    case NAVIGATION_TO_MANY_WITH_KEY:
+    case FUNCTIONIMPORT_WITH_KEY:
+        addNavigationSegment(property);
+        break;
+    default:
+        throw new RuntimeException("Unkown state:" + state);//NOSONAR
+    }
+    return this;
+  }
+  
+  private void addNavigationSegment(EdmNavigationProperty property) {
+    try {
+      state = property.getMultiplicity() == EdmMultiplicity.MANY? SegmentType.NAVIGATION_TO_MANY: 
+        SegmentType.NAVIGATION_TO_ONE;
+      segments.add(new Segment(state, property.getName()));
+    } catch (EdmException e) {
+      throw new RuntimeException("Unexpected EDM Exception: ", e);//NOSONAR
+    }
+  }
+
+  @Override
+  public EdmURIBuilder appendKeySegment(EdmProperty property, Object value) {
+    switch (state) {
+    case INITIAL:
+    case SIMPLEPROPERTY:
+    case COMPLEXPROPERTY:
+    case NAVIGATION_TO_ONE:
+    case NAVIGATION_TO_MANY_WITH_KEY:
+    case FUNCTIONIMPORT_WITH_KEY:
+    case FUNCTIONIMPORT:
+    case ENTITY:
+        throw new RuntimeException("Can't specify a key at this position");//NOSONAR
+    case ENTITYSET:
+        state = SegmentType.ENTITY;
+        appendKey(property, value);
+        break;
+    case NAVIGATION_TO_MANY:
+        state = SegmentType.NAVIGATION_TO_MANY_WITH_KEY;
+        appendKey(property, value);
+        break;
+    case FUNCTIONIMPORT_MANY:
+      state = SegmentType.FUNCTIONIMPORT_WITH_KEY;
+      appendKey(property, value);
+      break;
+    default:
+        throw new RuntimeException("Unkown state:" + state);//NOSONAR
+    }
+    return this;
+  }
+
+  private void appendKey(EdmProperty property, Object value) {
+    String key = "";
+    try {
+      key = getKey(property, value, false);
+    } catch (EdmSimpleTypeException e) {
+      throw new RuntimeException("Unexpected EDM Exception: ", e);//NOSONAR
+    } catch (EdmException e) {
+      throw new RuntimeException("Unexpected EDM Exception: ", e);//NOSONAR
+    }
+    segments.add(new Segment(SegmentType.KEY, key));
+  }
+
+  /**
+   * @param property
+   * @param value
+   * @return
+   * @throws EdmException
+   * @throws EdmSimpleTypeException
+   */
+  private String getKey(EdmProperty property, Object value, boolean isSegment) 
+      throws EdmException {
+    String key = "";
+    EdmSimpleType edmType = (EdmSimpleType) property.getType();
+    if (value instanceof String) {
+      value = Encoder.encode(value.toString()); //NOSONAR
+    }
+    if (!isSegment) {
+      key = "(" + edmType.valueToString(value, EdmLiteralKind.URI, property.getFacets()) + ")";
+    } else {
+      key = edmType.valueToString(value, EdmLiteralKind.URI, property.getFacets());
+    }
+    return key;
+  }
+
+  @Override
+  public EdmURIBuilder appendKeySegment(Map<EdmProperty, Object> segmentValues) {
+    switch (state) {
+    case INITIAL:
+    case SIMPLEPROPERTY:
+    case COMPLEXPROPERTY:
+    case NAVIGATION_TO_ONE:
+    case ENTITY:
+    case NAVIGATION_TO_MANY_WITH_KEY:
+    case FUNCTIONIMPORT:
+    case FUNCTIONIMPORT_WITH_KEY:
+        throw new RuntimeException("Can't specify a key at this position");//NOSONAR
+    case ENTITYSET:
+        state = SegmentType.ENTITY;
+        appendKey(segmentValues);
+        break;
+    case NAVIGATION_TO_MANY:
+        state = SegmentType.NAVIGATION_TO_MANY_WITH_KEY;
+        appendKey(segmentValues);
+        break;
+    case FUNCTIONIMPORT_MANY:
+      state = SegmentType.FUNCTIONIMPORT_WITH_KEY;
+      appendKey(segmentValues);
+      break;
+    default:
+        throw new RuntimeException("Unkown state:" + state);//NOSONAR
+    }
+    return this;
+  }
+  
+  private void appendKey(Map<EdmProperty, Object> segmentValues) {
+    String key = "";
+    try {
+      key = buildMultiKeySegment(segmentValues, ',');
+    } catch (EdmSimpleTypeException e) {
+      throw new RuntimeException("Unexpected EDM Exception: ", e);//NOSONAR
+    } catch (EdmException e) {
+      throw new RuntimeException("Unexpected EDM Exception: ", e);//NOSONAR
+    }
+    segments.add(new Segment(SegmentType.KEY, key));    
+  }
+
+  protected String buildMultiKeySegment(final Map<EdmProperty, Object> segmentValues,
+      final char separator) throws EdmException {
+    final StringBuilder keyBuilder = new StringBuilder().append('(');
+    for (Map.Entry<EdmProperty, Object> entry : segmentValues.entrySet()) {
+      keyBuilder.append(entry.getKey().getName()).append('=').append(
+          getKey((EdmProperty)entry.getKey(), entry.getValue(), true));
+      keyBuilder.append(separator);
+    }
+    keyBuilder.deleteCharAt(keyBuilder.length() - 1).append(')');
+
+    return keyBuilder.toString();
+  }
+  
+  @Override
+  public EdmURIBuilder filter(String filter) {
+    return replaceQueryOption(QueryOption.FILTER, filter);
+  }
+
+  @Override
+  public EdmURIBuilder select(String... selectItems) {
+    return addQueryOption(QueryOption.SELECT, UriUtil.join(selectItems, ","));
+  }
+
+  @Override
+  public EdmURIBuilder orderBy(String property) {
+    return addQueryOption(QueryOption.ORDERBY, property);
+  }
+
+  @Override
+  public EdmURIBuilder top(int top) {
+    return replaceQueryOption(QueryOption.TOP, String.valueOf(top));
+  }
+
+  @Override
+  public EdmURIBuilder skip(int skip) {
+    return replaceQueryOption(QueryOption.SKIP, String.valueOf(skip));
+  }
+  
+  @Override
+  public URI build() {
+    return UriUtil.getUri(segments, queryOptions, customQueryOptions, functionImportParameters);
+  }
+
+  @Override
+  public EdmURIBuilder addQueryOption(QueryOption option, String value) {
+    return addQueryOption(option.toString(), value, false);
+  }
+
+  public EdmURIBuilder replaceQueryOption(QueryOption option, String value) {
+    return addQueryOption(option.toString(), value, true);
+  }
+
+  public EdmURIBuilder addQueryOption(String option, String value, boolean replace) { //NOSONAR
+    if (option.equalsIgnoreCase(QueryOption.EXPAND.toString())) {
+      if (state == SegmentType.COUNT) {
+        throw new RuntimeException("Can't specify a query option " + option + " at this position");//NOSONAR
+      } else {
+        UriUtil.appendQueryOption(option, value, queryOptions, replace);
+      }
+    } else {
+      switch (state) {
+      case INITIAL:
+      case SIMPLEPROPERTY:
+      case COMPLEXPROPERTY:
+        throw new RuntimeException("Can't specify a query option " + option + " at this position");//NOSONAR
+      case NAVIGATION_TO_ONE:
+      case NAVIGATION_TO_MANY_WITH_KEY:
+      case ENTITY: 
+        entityQueryOption(option, value, replace);
+        break;
+      case ENTITYSET:
+      case NAVIGATION_TO_MANY:
+        UriUtil.appendQueryOption(option, value, queryOptions, replace);
+        break;
+      case COUNT:
+        countQueryOption(option, value, replace);
+        break;
+      default:
+          throw new RuntimeException("Unkown state:" + state);//NOSONAR
+      }
+    }
+    return this;
+  }
+
+  /**
+   * @param option
+   * @param value
+   * @param replace
+   */
+  private void countQueryOption(String option, String value, boolean replace) {
+    if (option.equalsIgnoreCase(QueryOption.SELECT.toString())) {
+      throw new RuntimeException("Can't specify a query option " + option + " at this position");//NOSONAR
+    } else {
+      UriUtil.appendQueryOption(option, value, queryOptions, replace);
+    }
+  }
+
+  /**
+   * @param option
+   * @param value
+   * @param replace
+   */
+  private void entityQueryOption(String option, String value, boolean replace) {
+    if (option.equalsIgnoreCase(QueryOption.SELECT.toString())) {
+      UriUtil.appendQueryOption(option, value, queryOptions, replace);
+    } else {
+      throw new RuntimeException("Can't specify a query option " + option + " at this position");//NOSONAR
+    }
+  }
+  
+  @Override
+  public EdmURIBuilder appendPropertySegment(EdmProperty property, String segmentValue) {
+    switch (state) {
+    case INITIAL:
+    case SIMPLEPROPERTY:
+    case NAVIGATION_TO_ONE:
+    case ENTITYSET:
+    case NAVIGATION_TO_MANY:
+    case FUNCTIONIMPORT_MANY:
+        throw new RuntimeException("Can't specify a property at this position");//NOSONAR
+    case COMPLEXPROPERTY:
+        appendProperty(property, segmentValue);
+        break;
+    case ENTITY:
+        appendProperty(property, segmentValue);
+        break;
+    case NAVIGATION_TO_MANY_WITH_KEY:
+    case FUNCTIONIMPORT_WITH_KEY:
+    case FUNCTIONIMPORT:
+        appendProperty(property, segmentValue);
+        break;
+    default:
+        throw new RuntimeException("Unkown state:" + state);//NOSONAR
+    }
+    return this;
+  }
+
+  private void appendProperty(EdmProperty property, String segmentValue) {
+    try {
+      state = property.getType().getKind() == EdmTypeKind.SIMPLE? SegmentType.SIMPLEPROPERTY : 
+        SegmentType.COMPLEXPROPERTY;
+    } catch (EdmException e) {
+      throw new RuntimeException("Unexpected EDM Exception: ", e);//NOSONAR
+    }
+    segments.add(new Segment(state, segmentValue));
+  }
+
+  @Override
+  public EdmURIBuilder expand(String... expandItems) {
+    return addQueryOption(QueryOption.EXPAND, UriUtil.join(expandItems, ","));
+  }
+
+  @Override
+  public EdmURIBuilder addCustomQueryOption(String paramName, Object paramValue) {
+    UriUtil.appendQueryOption(paramName, paramValue.toString(), 
+        customQueryOptions, true);
+    return this;
+  }
+
+  @Override
+  public EdmURIBuilder appendFunctionImportSegment(EdmFunctionImport functionImport) {
+    try {
+      state = functionImport.getReturnType() != null ? 
+          (functionImport.getReturnType().getMultiplicity() == EdmMultiplicity.MANY && 
+          functionImport.getReturnType().getType().getKind() == EdmTypeKind.ENTITY
+          ? SegmentType.FUNCTIONIMPORT_MANY : SegmentType.FUNCTIONIMPORT) : SegmentType.FUNCTIONIMPORT;
+      segments.add(new Segment(state, functionImport.getName()));
+    } catch (EdmException e) {
+      throw new RuntimeException("Unexpected EDM Exception: ", e);//NOSONAR
+    }
+    return this;
+  }
+
+  @Override
+  public EdmURIBuilder appendFunctionImportParameters(Map<EdmParameter, Object> functionImportParams) {
+    try {
+      if (functionImportParams != null) {
+        for (Map.Entry<EdmParameter, Object> param : functionImportParams.entrySet()) {
+          EdmParameter edmParam = param.getKey();
+          EdmSimpleType edmType = (EdmSimpleType) edmParam.getType();
+          Object value = param.getValue();
+          if (value instanceof String) {
+            value = value.toString();
+          } 
+          value = edmType.valueToString(value, EdmLiteralKind.URI, edmParam.getFacets());
+          functionImportParameters.put(edmParam.getName(), value);
+        }
+      }
+    } catch (EdmException e) {
+      throw new RuntimeException("Unexpected EDM Exception: ", e);//NOSONAR
+    }
+    return this;
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/uri/Segment.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/uri/Segment.java b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/uri/Segment.java
new file mode 100644
index 0000000..9cbf3bf
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/uri/Segment.java
@@ -0,0 +1,32 @@
+package org.apache.olingo.odata2.client.core.uri;
+
+import org.apache.olingo.odata2.client.api.uri.SegmentType;
+
+/**
+ * The objects of this class provide the uri segment type and value
+ *
+ */
+public class Segment {
+
+  private final SegmentType type;
+
+  private final String value;
+
+  /**
+   * 
+   * @param type
+   * @param value
+   */
+  public Segment(final SegmentType type, final String value) {
+    this.type = type;
+    this.value = value;
+  }
+
+  public SegmentType getType() {
+    return type;
+  }
+
+  public String getValue() {
+    return value;
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/uri/URIBuilderImpl.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/uri/URIBuilderImpl.java b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/uri/URIBuilderImpl.java
new file mode 100644
index 0000000..9fe74f4
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/uri/URIBuilderImpl.java
@@ -0,0 +1,217 @@
+package org.apache.olingo.odata2.client.core.uri;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.odata2.client.api.uri.QueryOption;
+import org.apache.olingo.odata2.client.api.uri.SegmentType;
+import org.apache.olingo.odata2.client.api.uri.URIBuilder;
+import org.apache.olingo.odata2.client.core.uri.util.UriUtil;
+import org.apache.olingo.odata2.core.commons.Encoder;
+
+/**
+ * This is a builder class that constructs URI without edm validations
+ *
+ */
+public class URIBuilderImpl implements URIBuilder {
+  protected final List<Segment> segments = new ArrayList<Segment>();
+  
+  /**
+   * Insertion-order map of query options.
+   */
+  protected final Map<String, String> queryOptions = new LinkedHashMap<String, String>();
+  
+  /**
+   * Insertion-order map of custom query options.
+   */
+  protected final Map<String, String> customQueryOptions = new LinkedHashMap<String, String>();
+  
+  /**
+   * Insertion-order map of function import parameters.
+   */
+  protected final Map<String, Object> functionImportParameters = new LinkedHashMap<String, Object>();
+  
+  /**
+   * Constructor.
+   *
+   * @param serviceRoot absolute URL (schema, host and port included) representing the location of the root of the data
+   * service.
+   */
+  public URIBuilderImpl(final String serviceRoot) {
+    segments.add(new Segment(SegmentType.INITIAL, serviceRoot));
+  }
+  
+  @Override
+  public URIBuilder appendCountSegment() {
+    segments.add(new Segment(SegmentType.COUNT, SegmentType.COUNT.getValue()));
+    return this;
+  }
+
+  @Override
+  public URIBuilder appendMetadataSegment() {
+    segments.add(new Segment(SegmentType.METADATA, SegmentType.METADATA.getValue()));
+    return this;
+  }
+
+  @Override
+  public URIBuilder format(String format) {
+    UriUtil.appendQueryOption(QueryOption.FORMAT.toString(), format, queryOptions, true);
+    return this;
+  }
+  
+  @Override
+  public URIBuilder appendValueSegment() {
+    segments.add(new Segment(SegmentType.VALUE, SegmentType.VALUE.getValue()));
+    return this;
+  }
+
+  @Override
+  public URIBuilder addQueryOption(QueryOption option, String value) {
+    UriUtil.appendQueryOption(option.toString(), value, queryOptions, false);
+    return this;
+  }
+
+  @Override
+  public URIBuilder filter(String filter) {
+    return replaceQueryOption(QueryOption.FILTER, filter);
+  }
+
+  @Override
+  public URIBuilder top(int top) {
+    return replaceQueryOption(QueryOption.TOP, String.valueOf(top));
+  }
+
+  @Override
+  public URIBuilder skip(int skip) {
+    return replaceQueryOption(QueryOption.SKIP, String.valueOf(skip));
+  }
+
+  @Override
+  public URIBuilder addCustomQueryOption(String paramName, Object paramValue) {
+    UriUtil.appendQueryOption(paramName, paramValue.toString(),
+        customQueryOptions, true);
+    return this;
+  }
+  
+  @Override
+  public URI build() {
+    return UriUtil.getUri(segments, queryOptions, customQueryOptions, functionImportParameters);
+  }
+  
+  @Override
+  public URIBuilder appendEntitySetSegment(String entitySet) {
+    segments.add(new Segment(SegmentType.ENTITYSET, entitySet));
+    return this;
+  }
+
+  @Override
+  public URIBuilder appendNavigationSegment(String navigationProperty) {
+    segments.add(new Segment(SegmentType.NAVIGATION, navigationProperty));
+    return this;
+  }
+
+  @Override
+  public URIBuilder appendKeySegment(Object value) {
+    String key = getKey(value, false);
+    segments.add(new Segment(SegmentType.KEY, key));
+    return this;
+  }
+
+  private String getKey(Object value, boolean isSegment) {
+    String key = "";
+    if (!isSegment) {
+      if (value instanceof String) {
+        value = Encoder.encode(value.toString()); //NOSONAR
+        key += "('" + value + "')";
+      } else {
+        key += "(" + value + ")";
+      }
+    } else {
+      if (value instanceof String) {
+        value = Encoder.encode(value.toString()); //NOSONAR
+        key += "'" + value + "'";
+      } else {
+        key += value;
+      }
+    }
+    return key;
+  }
+
+  @Override
+  public URIBuilder appendKeySegment(Map<String, Object> segmentValues) {
+    String key = buildMultiKeySegment(segmentValues, ',');
+    segments.add(new Segment(SegmentType.KEY, key));
+    return this;
+  }
+
+  private String buildMultiKeySegment(Map<String, Object> segmentValues, char separator) {
+    if (segmentValues == null || segmentValues.isEmpty()) {
+      return "";
+    } else {
+      final StringBuilder keyBuilder = new StringBuilder().append('(');
+      for (Map.Entry<String, Object> entry : segmentValues.entrySet()) {
+        keyBuilder.append(entry.getKey()).append('=').append(
+            getKey(entry.getValue(), true));
+        keyBuilder.append(separator);
+      }
+      keyBuilder.deleteCharAt(keyBuilder.length() - 1).append(')');
+
+      return keyBuilder.toString();
+    }
+  }
+
+  @Override
+  public URIBuilder appendPropertySegment(String segmentValue) {
+    segments.add(new Segment(SegmentType.PROPERTY, segmentValue));
+    return this;
+  }
+
+  @Override
+  public URIBuilder expand(String... expandItems) {
+    return addQueryOption(QueryOption.EXPAND, UriUtil.join(expandItems, ","));
+  }
+  
+  @Override
+  public URIBuilder select(String... selectItems) {
+    return addQueryOption(QueryOption.SELECT, UriUtil.join(selectItems, ","));
+  }
+
+  @Override
+  public URIBuilder orderBy(String order) {
+    return addQueryOption(QueryOption.ORDERBY, order);
+  }
+
+  /**
+   * 
+   * @param option
+   * @param value
+   * @return URIBuilder
+   */
+  public URIBuilder replaceQueryOption(QueryOption option, String value) {
+    UriUtil.appendQueryOption(option.toString(), value, queryOptions, true);
+    return this;
+  }
+
+  @Override
+  public URIBuilder appendFunctionImportSegment(String functionImport) {
+    segments.add(new Segment(SegmentType.FUNCTIONIMPORT, functionImport));
+    return this;
+  }
+
+  @Override
+  public URIBuilder appendFunctionImportParameters(Map<String, Object> functionImportParams) {
+    if (functionImportParams != null && !functionImportParams.isEmpty()) {
+      for (Map.Entry<String, Object> param : functionImportParams.entrySet()) {
+        Object value = param.getValue();
+        if (value instanceof String) {
+          value = "'" + value + "'";
+        }
+        functionImportParameters.put(param.getKey(), value);
+      }
+    }
+    return this;
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/uri/util/UriUtil.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/uri/util/UriUtil.java b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/uri/util/UriUtil.java
new file mode 100644
index 0000000..914d808
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/uri/util/UriUtil.java
@@ -0,0 +1,186 @@
+package org.apache.olingo.odata2.client.core.uri.util;
+
+import java.net.URI;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.odata2.client.api.uri.QueryOption;
+import org.apache.olingo.odata2.client.api.uri.SegmentType;
+import org.apache.olingo.odata2.client.core.uri.Segment;
+import org.apache.olingo.odata2.core.commons.Encoder;
+
+/**
+ * Util class
+ *
+ */
+public class UriUtil {
+
+  private UriUtil() {
+    
+  }
+  
+  /**
+   * 
+   * @param segments
+   * @param queryOptions
+   * @param customQueryOptions
+   * @param functionImportParameters 
+   * @return URI
+   */
+  public static URI getUri(List<Segment> segments, Map<String, String> queryOptions, 
+      Map<String, String> customQueryOptions, Map<String, Object> functionImportParameters) { //NOPMD  - suppressed
+    final StringBuilder segmentsBuilder = new StringBuilder();
+
+    if (segments.size() == 1 && segments.get(0).getType() == SegmentType.INITIAL
+        && customQueryOptions.isEmpty()
+        && queryOptions.isEmpty() && functionImportParameters.isEmpty()) {
+      segmentsBuilder.append(segments.get(0).getValue());
+      if (segmentsBuilder.charAt(segmentsBuilder.length() - 1) != '/') {
+        segmentsBuilder.append('/');
+      }
+      return URI.create(segmentsBuilder.toString());
+    }
+    for (Segment seg : segments) {
+      if (segmentsBuilder.length() > 0 && seg.getType() != SegmentType.KEY &&
+          seg.getType() != SegmentType.NAVIGATION_TO_MANY_WITH_KEY && 
+          seg.getType() != SegmentType.FUNCTIONIMPORT_WITH_KEY &&
+          segmentsBuilder.charAt(segmentsBuilder.length() - 1) != '/') {
+            segmentsBuilder.append('/');
+         }
+      segmentsBuilder.append(seg.getValue());
+    }
+
+    try {
+      if (!queryOptions.isEmpty()) {
+        appendQuerySegmentDelimiter(true, true, segmentsBuilder);
+        int i = 0;
+        for (Map.Entry<String, String> option : queryOptions.entrySet()) {
+        //Appends a system query option to uri builder
+          i++;
+          appendQuerySegments(QueryOption.valueOf(option.getKey()).getValue(), option.getValue(), 
+              segmentsBuilder, true);
+          if (i < queryOptions.size()) {
+            segmentsBuilder.append("&");
+          }
+        }
+      }
+      
+      if (!customQueryOptions.isEmpty()) {
+        appendQuerySegmentDelimiter(queryOptions.isEmpty(), true, segmentsBuilder);
+        int i = 0;
+        for (Map.Entry<String, String> option : customQueryOptions.entrySet()) {
+          //Appends a custom query option to uri builder
+          i++;
+          appendQuerySegments(option.getKey(), option.getValue(), 
+              segmentsBuilder, false);
+          if (i < customQueryOptions.size()) {
+            segmentsBuilder.append("&");
+          }
+        }
+      }
+      
+      if (!functionImportParameters.isEmpty()) {
+        appendQuerySegmentDelimiter(queryOptions.isEmpty(), customQueryOptions.isEmpty(), segmentsBuilder);
+        int i = 0;
+        for (Map.Entry<String, Object> funcParam : functionImportParameters.entrySet()) {
+          //Appends a function import URI with parameters to uri builder
+          i++;
+          appendQuerySegments(funcParam.getKey(), funcParam.getValue(), 
+              segmentsBuilder, false);
+          if (i < functionImportParameters.size()) {
+            segmentsBuilder.append("&");
+          }
+        }
+      }
+
+      return URI.create(segmentsBuilder.toString());
+    } catch (IllegalArgumentException e) {
+      throw new IllegalArgumentException("Could not build valid URI", e);
+    }
+  }
+  
+  /**
+   * 
+   * @param isQueryOptions
+   * @param isCustomQueryOptions
+   * @param segmentsBuilder
+   */
+  private static void appendQuerySegmentDelimiter(boolean isQueryOptions, 
+      boolean isCustomQueryOptions, StringBuilder segmentsBuilder) {
+    if (!isQueryOptions || !isCustomQueryOptions) {
+      segmentsBuilder.append("&");
+    } else {
+      segmentsBuilder.append("?");
+    }
+  }
+  
+  /**
+   * 
+   * @param name
+   * @param value
+   * @param segmentsBuilder
+   */
+  private static void appendQuerySegments(String name, Object value, 
+      StringBuilder segmentsBuilder, boolean isQueryOption) {
+    if (isQueryOption) {
+      segmentsBuilder.append(name); 
+    } else {
+      segmentsBuilder.append(Encoder.encode(name)); 
+    }
+    segmentsBuilder.append("="); 
+    segmentsBuilder.append(Encoder.encode(value.toString()));
+  }
+
+  /**
+   * 
+   * @param items
+   * @param separator
+   * @return String
+   */
+  public static String join(String[] items, String separator) {
+    return join(items, separator, 0, items.length);
+  }
+
+  private static String join(String[] items, String separator, int startIndex, int endIndex) {
+    if (items == null) {
+      return null;
+    }
+    if (separator == null) {
+      separator = ""; //NOSONAR
+    }
+    
+    final int noOfItems = endIndex - startIndex;
+    if (noOfItems <= 0) {
+      return "";
+    }
+
+    final StringBuilder buf = new StringBuilder(noOfItems * 16);
+
+    for (int i = startIndex; i < endIndex; i++) {
+      if (i > startIndex) {
+        buf.append(separator);
+      }
+      if (items[i] != null) {
+        buf.append(items[i]);
+      }
+    }
+    return buf.toString();
+  }
+  
+  /**
+   * 
+   * @param paramName
+   * @param paramValue
+   * @param queryOptions
+   * @param replace
+   */
+  public static void appendQueryOption(String paramName, String paramValue, Map<String, 
+      String> queryOptions, boolean replace) {
+    final StringBuilder builder = new StringBuilder();
+    if (!replace && queryOptions.containsKey(paramName)) {
+      builder.append(queryOptions.get(paramName)).append(',');
+    }
+    builder.append(paramValue);
+    queryOptions.put(paramName, builder.toString());
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/edm/impl/EdmAnnotationImplTest.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/edm/impl/EdmAnnotationImplTest.java b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/edm/impl/EdmAnnotationImplTest.java
new file mode 100644
index 0000000..032809e
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/edm/impl/EdmAnnotationImplTest.java
@@ -0,0 +1,95 @@
+/*******************************************************************************
+ * 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.client.core.edm.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.EdmAnnotationAttribute;
+import org.apache.olingo.odata2.api.edm.EdmAnnotationElement;
+import org.apache.olingo.odata2.client.core.edm.Impl.EdmAnnotationAttributeImpl;
+import org.apache.olingo.odata2.client.core.edm.Impl.EdmAnnotationElementImpl;
+import org.apache.olingo.odata2.client.core.edm.Impl.EdmAnnotationsImpl;
+import org.junit.Test;
+
+public class EdmAnnotationImplTest {
+
+  @Test
+  public void annotationAttributeTest(){
+    EdmAnnotationAttributeImpl annotation = new EdmAnnotationAttributeImpl();
+    annotation.setName("name");
+    annotation.setNamespace("namespace");
+    annotation.setPrefix("prefix");
+    annotation.setText("text");
+    assertEquals("name", annotation.getName());
+    assertEquals("namespace", annotation.getNamespace());
+    assertEquals("prefix", annotation.getPrefix());
+    assertEquals("text", annotation.getText());
+  }
+  
+  @Test
+  public void annotationElementTest(){
+    EdmAnnotationElementImpl annotation = new EdmAnnotationElementImpl();
+    annotation.setName("name");
+    annotation.setNamespace("namespace");
+    annotation.setPrefix("prefix");
+    annotation.setText("text");
+    annotation.setAttributes(null);
+    annotation.setChildElements(null);
+    assertEquals("name", annotation.getName());
+    assertEquals("namespace", annotation.getNamespace());
+    assertEquals("prefix", annotation.getPrefix());
+    assertEquals("text", annotation.getText());
+    assertNull(annotation.getAttributes());
+    assertNull(annotation.getChildElements());
+  }
+  
+  @Test
+  public void annotationTest(){
+    EdmAnnotationsImpl annotation = new EdmAnnotationsImpl();
+    EdmAnnotationElementImpl annotationElement = new EdmAnnotationElementImpl();
+    EdmAnnotationAttributeImpl annotationAttribute = new EdmAnnotationAttributeImpl();
+    List<EdmAnnotationAttribute> annotationAttributeList = 
+        new ArrayList<EdmAnnotationAttribute>();  
+    List<EdmAnnotationElement> annotationElementList = 
+        new ArrayList<EdmAnnotationElement>();        
+    annotationAttributeList.add(annotationAttribute);
+    annotationElementList.add(annotationElement);
+    annotationAttribute.setName("name");
+    annotationAttribute.setNamespace("namespace");
+    annotationAttribute.setPrefix("prefix");
+    annotationAttribute.setText("text");
+    annotationElement.setName("name");
+    annotationElement.setNamespace("namespace");
+    annotationElement.setPrefix("prefix");
+    annotationElement.setText("text");
+    annotationElement.setAttributes(annotationAttributeList);
+    annotationElement.setChildElements(null);
+    annotation.setAnnotationAttributes(annotationAttributeList);
+    annotation.setAnnotationElements(annotationElementList);
+    assertNotNull(annotation.getAnnotationAttribute("name", "namespace"));
+    assertNotNull(annotation.getAnnotationAttributes());
+    assertNotNull(annotation.getAnnotationElement("name", "namespace"));
+    assertNotNull(annotation.getAnnotationElements());
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/edm/impl/EdmAssociationImplTest.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/edm/impl/EdmAssociationImplTest.java b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/edm/impl/EdmAssociationImplTest.java
new file mode 100644
index 0000000..934e289
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/edm/impl/EdmAssociationImplTest.java
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * 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.client.core.edm.impl;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import java.util.ArrayList;
+
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.client.core.edm.EdmMetadataAssociationEnd;
+import org.apache.olingo.odata2.client.core.edm.Impl.EdmAnnotationsImpl;
+import org.apache.olingo.odata2.client.core.edm.Impl.EdmAssociationEndImpl;
+import org.apache.olingo.odata2.client.core.edm.Impl.EdmAssociationImpl;
+import org.apache.olingo.odata2.client.core.edm.Impl.EdmDocumentationImpl;
+import org.apache.olingo.odata2.client.core.edm.Impl.EdmImpl;
+import org.apache.olingo.odata2.client.core.edm.Impl.EdmReferentialConstraintImpl;
+import org.junit.Test;
+
+public class EdmAssociationImplTest {
+
+  @Test
+  public void associationTest() throws EdmException {
+    EdmAssociationImpl association= new EdmAssociationImpl();
+    ArrayList<EdmMetadataAssociationEnd> ends = new ArrayList<EdmMetadataAssociationEnd>();
+    ends.add(new EdmAssociationEndImpl());
+    ends.add(new EdmAssociationEndImpl());
+    association.setAnnotations(new EdmAnnotationsImpl());
+    association.setAssociationEnds(ends);
+    association.setDocumentation(new EdmDocumentationImpl());
+    association.setEdm(new EdmImpl());
+    association.setName("name");
+    association.setNamespace("namespace");
+    association.setReferentialConstraint(new EdmReferentialConstraintImpl());
+    assertNotNull(association);
+    assertNotNull(association.getAnnotations());
+    assertNotNull(association.getAssociationEnds());
+    assertNotNull(association.getDocumentation());
+    assertNull(association.getEnd("role"));
+    assertNotNull(association.getEnd1());
+    assertNotNull(association.getEnd2());
+    assertNull(association.getEndMultiplicity("role"));
+    assertNotNull(association.getKind());
+    assertNotNull(association.getName());
+    assertNotNull(association.getNamespace());
+    assertNotNull(association.getReferentialConstraint());
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/edm/impl/EdmDocumentationImplTest.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/edm/impl/EdmDocumentationImplTest.java b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/edm/impl/EdmDocumentationImplTest.java
new file mode 100644
index 0000000..1043d1b
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/edm/impl/EdmDocumentationImplTest.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * 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.client.core.edm.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.EdmAnnotationAttribute;
+import org.apache.olingo.odata2.api.edm.EdmAnnotationElement;
+import org.apache.olingo.odata2.client.core.edm.Impl.EdmDocumentationImpl;
+import org.junit.Test;
+
+public class EdmDocumentationImplTest {
+
+  @Test
+  public void testDocumentation(){
+    EdmDocumentationImpl doc = new EdmDocumentationImpl();
+    List<EdmAnnotationAttribute> annotationAttributes = 
+        new ArrayList<EdmAnnotationAttribute>();
+    doc.setAnnotationAttributes(annotationAttributes);
+    List<EdmAnnotationElement> annotationElements = 
+        new ArrayList<EdmAnnotationElement>();
+    doc.setAnnotationElements(annotationElements );
+    doc.setLongDescription("longDescription");
+    doc.setSummary("summary");
+    assertNotNull(doc.getAnnotationAttributes());
+    assertNotNull(doc.getAnnotationElements());
+    assertNotNull(doc.getLongDescription());
+    assertNotNull(doc.getClass());
+    assertEquals(doc.getLongDescription(),"longDescription");
+    assertEquals(doc.getSummary(), "summary");
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/edm/impl/EdmEntityImplTest.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/edm/impl/EdmEntityImplTest.java b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/edm/impl/EdmEntityImplTest.java
new file mode 100644
index 0000000..ada8553
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/edm/impl/EdmEntityImplTest.java
@@ -0,0 +1,215 @@
+/*******************************************************************************
+ * 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.client.core.edm.impl;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.edm.EdmAssociation;
+import org.apache.olingo.odata2.api.edm.EdmAssociationSet;
+import org.apache.olingo.odata2.api.edm.EdmComplexType;
+import org.apache.olingo.odata2.api.edm.EdmCustomizableFeedMappings;
+import org.apache.olingo.odata2.api.edm.EdmEntityContainer;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmFunctionImport;
+import org.apache.olingo.odata2.api.edm.EdmMapping;
+import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.edm.EdmTypeKind;
+import org.apache.olingo.odata2.api.edm.FullQualifiedName;
+import org.apache.olingo.odata2.client.core.edm.Impl.EdmAnnotationsImpl;
+import org.apache.olingo.odata2.client.core.edm.Impl.EdmAssociationImpl;
+import org.apache.olingo.odata2.client.core.edm.Impl.EdmComplexTypeImpl;
+import org.apache.olingo.odata2.client.core.edm.Impl.EdmCustomizableFeedMappingsImpl;
+import org.apache.olingo.odata2.client.core.edm.Impl.EdmDocumentationImpl;
+import org.apache.olingo.odata2.client.core.edm.Impl.EdmEntityContainerImpl;
+import org.apache.olingo.odata2.client.core.edm.Impl.EdmEntitySetImpl;
+import org.apache.olingo.odata2.client.core.edm.Impl.EdmEntityTypeImpl;
+import org.apache.olingo.odata2.client.core.edm.Impl.EdmImpl;
+import org.apache.olingo.odata2.client.core.edm.Impl.EdmMappingImpl;
+import org.apache.olingo.odata2.client.core.edm.Impl.EdmNavigationPropertyImpl;
+import org.junit.Before;
+import org.junit.Test;
+
+public class EdmEntityImplTest {
+
+  private EdmAnnotationsImpl annotations;
+  private EdmDocumentationImpl documentation;
+  private EdmImpl edm;
+  private EdmEntityContainerImpl edmEntityContainer;
+  private EdmEntityTypeImpl edmEntityType;
+  private FullQualifiedName fqName;
+  private FullQualifiedName entityTypeName;
+  private EdmMapping mapping;
+  private String name;
+  private EdmCustomizableFeedMappings edmCustomizableFeedMappings;
+  private List<EdmProperty> edmKeyProperties;
+  private List<String> edmKeyPropertyNames;
+  private List<EdmNavigationProperty> navigationProperties;
+  private EdmComplexTypeImpl structuralType;
+
+  @Before
+  public void initialize() throws EdmException {
+    annotations = new EdmAnnotationsImpl();
+    documentation = new EdmDocumentationImpl();
+    edm = new EdmImpl();
+    edmEntityContainer = new EdmEntityContainerImpl(edm);
+    edmEntityType = new EdmEntityTypeImpl();
+    fqName = new FullQualifiedName("namespace", "name");
+    entityTypeName = new FullQualifiedName("namespace", "name");
+    mapping = new EdmMappingImpl();
+    name = "name";
+    edmCustomizableFeedMappings = new EdmCustomizableFeedMappingsImpl();
+    edmKeyProperties = new ArrayList<EdmProperty>();
+    edmKeyPropertyNames = new ArrayList<String>();
+    navigationProperties = new ArrayList<EdmNavigationProperty>();
+    structuralType = new EdmComplexTypeImpl();
+    structuralType.setName("name");
+    structuralType.setNamespace("namespace");
+    structuralType.setMapping(mapping);
+
+    Map<FullQualifiedName, EdmComplexType> edmComplexTypes = new HashMap<FullQualifiedName, EdmComplexType>();
+    edmComplexTypes.put(new FullQualifiedName("namespace", "name"), structuralType);
+    edm.setEdmComplexTypes(edmComplexTypes);
+
+    Map<FullQualifiedName, EdmAssociation> associationmap = new HashMap<FullQualifiedName, EdmAssociation>();
+    associationmap.put(entityTypeName, new EdmAssociationImpl());
+    edm.setEdmAssociations(associationmap);
+    
+    Map<String, String> aliasToNamespaceInfo = new HashMap<String, String>();
+    aliasToNamespaceInfo.put("alias", "namespace");
+    edm.setAliasToNamespaceInfo(aliasToNamespaceInfo );
+  }
+
+  @Test
+  public void entitySetTest() throws EdmException {
+    EdmEntitySetImpl entity = new EdmEntitySetImpl();
+    entity.setAnnotations(annotations);
+    entity.setDocumentation(documentation);
+    entity.setEdm(edm);
+    entity.setEdmEntityContainer(edmEntityContainer);
+    entity.setEdmEntityType(edmEntityType);
+    entity.setEdmEntityTypeName(fqName);
+    entity.setEntityTypeName(entityTypeName);
+    entity.setMapping(mapping);
+    entity.setName(name);
+    assertNotNull(entity);
+    assertNotNull(entity.getAnnotations());
+    assertNotNull(entity.getDocumentation());
+    assertNotNull(entity.getEdmEntityContainer());
+    assertNotNull(entity.getEdmEntityType());
+    assertNotNull(entity.getEntityContainer());
+    assertNotNull(entity.getEntityType());
+    assertNotNull(entity.getEntityTypeName());
+    assertNotNull(entity.getMapping());
+    assertNotNull(entity.getName());
+
+  }
+
+  @Test
+  public void entityTypeTest() throws EdmException {
+    EdmEntityTypeImpl entity = new EdmEntityTypeImpl();
+    entity.setAnnotations(annotations);
+    entity.setAbstract(true);
+    entity.setEdm(edm);
+    entity.setBaseType(entityTypeName);
+    entity.setCustomizableFeedMappings(edmCustomizableFeedMappings);
+    entity.setEdmBaseType(edmEntityType);
+    entity.setEdmKeyProperties(edmKeyProperties);
+    entity.setEdmKeyPropertyNames(edmKeyPropertyNames);
+    entity.setName(name);
+    entity.setEdmNavigationPropertyNames(edmKeyPropertyNames);
+    entity.setEdmPropertyNames(edmKeyPropertyNames);
+    entity.setEdmTypeKind(EdmTypeKind.SIMPLE);
+    entity.setHasStream(true);
+    entity.setNamespace("namespace");
+    entity.setNavigationProperties(navigationProperties);
+    entity.setProperties(edmKeyProperties);
+    entity.setStructuralType(structuralType);
+    assertNotNull(entity);
+    assertNotNull(entity.getAnnotations());
+    assertNotNull(entity.getBaseType());
+    assertNotNull(entity.getBaseTypeName());
+    assertNotNull(entity.getCustomizableFeedMappings());
+    assertNotNull(entity.getEdmBaseType());
+    assertNotNull(entity.getEdmTypeKind());
+    assertNotNull(entity.getKeyProperties());
+    assertNotNull(entity.getKeyPropertyNames());
+    assertNotNull(entity.getKind());
+    assertNotNull(entity.getMapping());
+    assertNotNull(entity.getName());
+    assertNotNull(entity.getNamespace());
+    assertNotNull(entity.getNavigationPropertyNames());
+    assertNotNull(entity.getProperties());
+    assertNotNull(entity.getPropertyNames());
+    assertNotNull(entity.getStructuralType());
+
+  }
+
+  @Test
+  public void entityContainerTest() throws EdmException {
+    EdmEntityContainerImpl cont = new EdmEntityContainerImpl(edm);
+    cont.setAnnotations(annotations);
+    cont.setDefaultContainer(true);
+    cont.setDocumentation(documentation);
+    cont.setEdm(edm);
+    cont.setEdmAssociationSets(new ArrayList<EdmAssociationSet>());
+    List<EdmEntitySet> entitySets = new ArrayList<EdmEntitySet>();
+    cont.setEdmEntitySets(entitySets);
+    cont.setEdmExtendedEntityContainer(new EdmEntityContainerImpl(edm));
+    cont.setEdmFunctionImports(new ArrayList<EdmFunctionImport>());
+    cont.setEntityContainerHierachy(new ArrayList<EdmEntityContainer>());
+    cont.setExtendz(name);
+    cont.setName(name);
+    assertNotNull(cont);
+    EdmEntitySet entitySet = new EdmEntitySetImpl();
+    ((EdmEntitySetImpl) entitySet).setName(name);
+    EdmNavigationProperty nav = new EdmNavigationPropertyImpl();
+    ((EdmNavigationPropertyImpl) nav).setEdm(edm);
+    ((EdmNavigationPropertyImpl) nav).setRelationshipName(entityTypeName);
+    entitySets.add(entitySet);
+    assertNotNull(cont.getAssociationSets());
+    assertNotNull(cont.getDocumentation());
+    assertNotNull(cont.getEdm());
+    assertNotNull(cont.getEdmAssociationSets());
+    assertNotNull(cont.getEdmEntitySets());
+    assertNotNull(cont.getEdmExtendedEntityContainer());
+    assertNotNull(cont.getEdmFunctionImports());
+    assertNotNull(cont.getEntitySet(name));
+    assertNotNull(cont.getEntitySets());
+    assertNotNull(cont.getExtendz());
+    assertNull(cont.getFunctionImport(name));
+    assertNotNull(cont.getName());
+  }
+
+  @Test
+  public void complexTypeTest() throws EdmException {
+    EdmComplexType complexType = edm.getComplexType("namespace", "name");
+    assertNotNull(complexType);
+    
+    complexType = edm.getComplexType("alias", "name");
+    assertNotNull(complexType);
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/edm/impl/EdmMappingImplTest.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/edm/impl/EdmMappingImplTest.java b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/edm/impl/EdmMappingImplTest.java
new file mode 100644
index 0000000..25cf026
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/edm/impl/EdmMappingImplTest.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * 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.client.core.edm.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import org.apache.olingo.odata2.client.core.edm.Impl.EdmMappingImpl;
+import org.junit.Test;
+
+public class EdmMappingImplTest {
+
+  @Test
+  public void mapTest() {
+    EdmMappingImpl map= new EdmMappingImpl();
+    map.setInternalName("name");
+    map.setMediaResourceMimeTypeKey("media");
+    map.setMediaResourceSourceKey("mediaKey");
+    map.setObject(null);
+    assertNotNull(map);
+    assertEquals("name", map.getInternalName());
+    assertEquals("media", map.getMediaResourceMimeTypeKey());
+    assertEquals("mediaKey", map.getMediaResourceSourceKey());
+    assertNull(map.getObject());
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/edm/impl/EdmOnDeleteImplTest.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/edm/impl/EdmOnDeleteImplTest.java b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/edm/impl/EdmOnDeleteImplTest.java
new file mode 100644
index 0000000..c7ef400
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/edm/impl/EdmOnDeleteImplTest.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * 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.client.core.edm.impl;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import java.util.ArrayList;
+
+import org.apache.olingo.odata2.api.edm.EdmAnnotationAttribute;
+import org.apache.olingo.odata2.api.edm.EdmAnnotationElement;
+import org.apache.olingo.odata2.client.core.edm.Impl.EdmDocumentationImpl;
+import org.apache.olingo.odata2.client.core.edm.Impl.EdmOnDeleteImpl;
+import org.junit.Test;
+
+public class EdmOnDeleteImplTest {
+
+  @Test
+  public void testOnDelete(){
+    EdmOnDeleteImpl del = new EdmOnDeleteImpl();
+    del.setAction(null);
+    del.setAnnotationAttributes(new ArrayList<EdmAnnotationAttribute>());
+    del.setAnnotationElements(new ArrayList<EdmAnnotationElement>());
+    del.setDocumentation(new EdmDocumentationImpl());
+    assertNotNull(del);
+    assertNull(del.getAction());
+    assertNotNull(del.getAnnotationAttributes());
+    assertNotNull(del.getAnnotationElements());
+    assertNotNull(del.getDocumentation());
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/AbstractProviderTest.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/AbstractProviderTest.java b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/AbstractProviderTest.java
new file mode 100644
index 0000000..ad04601
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/AbstractProviderTest.java
@@ -0,0 +1,214 @@
+/*******************************************************************************
+ * 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.client.core.ep;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Calendar;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.TimeZone;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.ep.callback.TombstoneCallback;
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.api.processor.ODataContext;
+import org.apache.olingo.odata2.api.uri.PathInfo;
+import org.apache.olingo.odata2.client.api.ep.Entity;
+import org.apache.olingo.odata2.client.api.ep.EntityCollection;
+import org.apache.olingo.odata2.client.api.ep.EntitySerializerProperties;
+import org.custommonkey.xmlunit.SimpleNamespaceContext;
+import org.custommonkey.xmlunit.XMLUnit;
+import org.junit.Before;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ *  
+*/
+public abstract class AbstractProviderTest extends AbstractXmlProducerTestHelper{
+
+
+  public AbstractProviderTest(final StreamWriterImplType type) {
+    super(type);
+  }
+
+  protected final Logger log = LoggerFactory.getLogger(this.getClass());
+
+  protected static final URI BASE_URI;
+
+  static {
+    try {
+      BASE_URI = new URI("http://host:80/service/");
+    } catch (URISyntaxException e) {
+      throw new RuntimeException(e);
+    }
+  }
+  protected static final EntitySerializerProperties DEFAULT_PROPERTIES =
+      EntitySerializerProperties.serviceRoot(
+      BASE_URI).includeMetadata(true).build();
+
+  protected Entity employeeData;
+
+  protected EntityCollection employeesData;
+
+  protected Entity photoData;
+
+  protected Entity roomData;
+
+  protected Entity buildingData;
+
+  protected EntityCollection roomsData;
+
+  {
+    employeeData = new Entity();
+
+    Calendar date = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
+    date.clear();
+    date.set(1999, 0, 1);
+
+    employeeData.addProperty("EmployeeId", "1");
+    employeeData.addProperty("ImmageUrl", null);
+    employeeData.addProperty("ManagerId", "1");
+    employeeData.addProperty("Age", new Integer(52));
+    employeeData.addProperty("RoomId", "1");
+    employeeData.addProperty("EntryDate", date);
+    employeeData.addProperty("TeamId", "42");
+    employeeData.addProperty("EmployeeName", "Walter Winter");
+    // employeeData.put("getImageType", "abc");
+
+    Entity locationData = new Entity();
+    Entity cityData = new Entity();
+    cityData.addProperty("PostalCode", "33470");
+    cityData.addProperty("CityName", "Duckburg");
+    locationData.addProperty("City", cityData);
+    locationData.addProperty("Country", "Calisota");
+
+    employeeData.addProperty("Location", locationData);
+
+    Entity employeeData2 = new Entity();
+    employeeData2.addProperty("EmployeeId", "1");
+    employeeData2.addProperty("ImmageUrl", null);
+    employeeData2.addProperty("ManagerId", "1");
+    employeeData2.addProperty("Age", new Integer(52));
+    employeeData2.addProperty("RoomId", "1");
+    employeeData2.addProperty("EntryDate", date);
+    employeeData2.addProperty("TeamId", "42");
+    employeeData2.addProperty("EmployeeName", "Walter Winter");
+
+    Entity locationData2 = new Entity();
+    Entity cityData2 = new Entity();
+    cityData2.addProperty("PostalCode", "33470");
+    cityData2.addProperty("CityName", "Duckburg");
+    locationData2.addProperty("City", cityData2);
+    locationData2.addProperty("Country", "Calisota");
+
+    employeeData2.addProperty("Location", locationData2);
+
+    employeesData = new EntityCollection();
+    employeesData.addEntity(employeeData);
+    employeesData.addEntity(employeeData2);
+
+    photoData = new Entity();
+    photoData.addProperty("Id", Integer.valueOf(1));
+    photoData.addProperty("Name", "Mona Lisa");
+    photoData.addProperty("Type", "image/png");
+    photoData
+        .addProperty(
+            "ImageUrl",
+            "http://www.mopo.de/image/view/2012/6/4/16548086,13385561,medRes,maxh,234,maxw,234," +
+                "Parodia_Mona_Lisa_Lego_Hamburger_Morgenpost.jpg");
+    Entity imageData = new Entity();
+    imageData.addProperty("Image", new byte[] { 1, 2, 3, 4 });
+    imageData.addProperty("getImageType", "image/png");
+    photoData.addProperty("Image", imageData);
+    photoData.addProperty("BinaryData", new byte[] { -1, -2, -3, -4 });
+    photoData.addProperty("Содержание", "В лесу шумит водопад. Если он не торопится просп воды");
+
+    roomData = new Entity();
+    roomData.addProperty("Id", "1");
+    roomData.addProperty("Name", "Neu Schwanstein");
+    roomData.addProperty("Seats", new Integer(20));
+    roomData.addProperty("Version", new Integer(3));
+
+    buildingData = new Entity();
+    buildingData.addProperty("Id", "1");
+    buildingData.addProperty("Name", "WDF03");
+    buildingData.addProperty("Image", "image");
+  }
+
+  protected void initializeRoomData(final int count) {
+    roomsData = new EntityCollection();
+    for (int i = 1; i <= count; i++) {
+      Entity tmp = new Entity();
+      tmp.addProperty("Id", "" + i);
+      tmp.addProperty("Name", "Neu Schwanstein" + i);
+      tmp.addProperty("Seats", new Integer(20));
+      tmp.addProperty("Version", new Integer(3));
+      roomsData.addEntity(tmp);
+    }
+  }
+
+  @Before
+  public void setXmlNamespacePrefixes() throws Exception {
+    Map<String, String> prefixMap = new HashMap<String, String>();
+    prefixMap.put("a", Edm.NAMESPACE_ATOM_2005);
+    prefixMap.put("d", Edm.NAMESPACE_D_2007_08);
+    prefixMap.put("m", Edm.NAMESPACE_M_2007_08);
+    prefixMap.put("xml", Edm.NAMESPACE_XML_1998);
+    prefixMap.put("ру", "http://localhost");
+    prefixMap.put("custom", "http://localhost");
+    prefixMap.put("at", TombstoneCallback.NAMESPACE_TOMBSTONE);
+    XMLUnit.setXpathNamespaceContext(new SimpleNamespaceContext(prefixMap));
+  }
+
+  protected ODataContext createContextMock() throws ODataException {
+    PathInfo pathInfo = mock(PathInfo.class);
+    when(pathInfo.getServiceRoot()).thenReturn(BASE_URI);
+    ODataContext ctx = mock(ODataContext.class);
+    when(ctx.getPathInfo()).thenReturn(pathInfo);
+    return ctx;
+  }
+
+  protected AtomSerializerDeserializer createAtomEntityProvider() throws EntityProviderException {
+    return new AtomSerializerDeserializer();
+  }
+
+  public Entity getEmployeeData() {
+    return employeeData;
+  }
+
+  public EntityCollection getEmployeesData() {
+    return employeesData;
+  }
+
+  public Entity getRoomData() {
+    return roomData;
+  }
+
+  public EntityCollection getRoomsData() {
+    return roomsData;
+  }
+
+
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/AbstractXmlProducerTestHelper.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/AbstractXmlProducerTestHelper.java b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/AbstractXmlProducerTestHelper.java
new file mode 100644
index 0000000..052b931
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/AbstractXmlProducerTestHelper.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * 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.client.core.ep;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.olingo.odata2.testutil.fit.BaseTest;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public abstract class AbstractXmlProducerTestHelper extends BaseTest {
+
+  public enum StreamWriterImplType {
+    WOODSTOCKIMPL, SUNINTERNALIMPL;
+  }
+
+  // CHECKSTYLE:OFF
+  public AbstractXmlProducerTestHelper(final StreamWriterImplType type) {
+    switch (type) {
+    case WOODSTOCKIMPL:
+      System.setProperty("javax.xml.stream.XMLInputFactory", "com.ctc.wstx.stax.WstxInputFactory"); // NOSONAR
+      System.setProperty("javax.xml.stream.XMLOutputFactory", "com.ctc.wstx.stax.WstxOutputFactory"); // NOSONAR
+      break;
+    case SUNINTERNALIMPL:
+      System.setProperty("javax.xml.stream.XMLInputFactory", "com.sun.xml.internal.stream.XMLInputFactoryImpl"); // NOSONAR
+      System.setProperty("javax.xml.stream.XMLOutputFactory", "com.sun.xml.internal.stream.XMLOutputFactoryImpl"); // NOSONAR
+      break;
+    default:
+      System.setProperty("javax.xml.stream.XMLOutputFactory", "com.sun.xml.internal.stream.XMLOutputFactoryImpl"); // NOSONAR
+      System.setProperty("javax.xml.stream.XMLInputFactory", "com.sun.xml.internal.stream.XMLInputFactoryImpl"); // NOSONAR
+      break;
+    }
+  }
+
+  // CHECKSTYLE:On
+
+  @Parameterized.Parameters
+  public static List<Object[]> data() {
+    // If desired this can be made dependent on runtime variables
+    Object[][] a;
+    a = new Object[2][1];
+    a[0][0] = StreamWriterImplType.WOODSTOCKIMPL;
+    a[1][0] = StreamWriterImplType.SUNINTERNALIMPL;
+
+    return Arrays.asList(a);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/DeserializerPropertiesTest.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/DeserializerPropertiesTest.java b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/DeserializerPropertiesTest.java
new file mode 100644
index 0000000..96e95bf
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/DeserializerPropertiesTest.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * 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.client.core.ep;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.sql.Timestamp;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.olingo.odata2.client.api.ep.DeserializerProperties;
+import org.apache.olingo.odata2.testutil.fit.BaseTest;
+import org.junit.Test;
+
+/**
+ *  
+ */
+public class DeserializerPropertiesTest extends BaseTest {
+
+  @Test
+  public void buildReadProperties() throws Exception {
+    DeserializerProperties properties = DeserializerProperties.init()
+        .build();
+
+    assertNotNull(properties.getTypeMappings());
+    assertEquals(0, properties.getTypeMappings().size());
+    assertNotNull(properties.getValidatedPrefixNamespaceUris());
+    assertEquals(0, properties.getValidatedPrefixNamespaceUris().size());
+   }
+
+  @Test
+  public void buildPropertiesAllSet() throws Exception {
+    Map<String, String> namespaces = new HashMap<String, String>();
+    namespaces.put("aNamespace", new String());
+    Map<String, Object> typeMappings = new HashMap<String, Object>();
+    typeMappings.put("Property", Timestamp.class);
+    final DeserializerProperties properties = DeserializerProperties.init()
+        .addValidatedPrefixes(namespaces)
+        .isValidatingFacets(true)
+        .addTypeMappings(typeMappings)
+        .build();
+
+    assertNotNull(properties.getValidatedPrefixNamespaceUris());
+    assertNotNull(properties.getTypeMappings());
+    assertTrue("validating facets should be set", properties.isValidatingFacets());
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/JSON_XMLErrorConsumerTest.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/JSON_XMLErrorConsumerTest.java b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/JSON_XMLErrorConsumerTest.java
new file mode 100644
index 0000000..b9488f6
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/JSON_XMLErrorConsumerTest.java
@@ -0,0 +1,70 @@
+/*******************************************************************************
+ * 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.client.core.ep;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.Locale;
+
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.processor.ODataErrorContext;
+import org.apache.olingo.odata2.client.api.ODataClient;
+import org.apache.olingo.odata2.client.core.ep.deserializer.AbstractDeserializerTest;
+import org.apache.olingo.odata2.testutil.helper.StringHelper;
+import org.junit.Test;
+
+/**
+ *  
+ */
+public class JSON_XMLErrorConsumerTest extends AbstractDeserializerTest {
+
+  private static final String JSON = "application/json";
+  private static final String XML = "application/xml";
+  
+  @Test
+  public void readErrorDocumentJson() throws EntityProviderException {
+    ODataClient providerFacade = ODataClient.newInstance();
+    String errorDoc = "{\"error\":{\"code\":\"ErrorCode\",\"message\":{\"lang\":\"en-US\",\"value\":\"Message\"}}}";
+    ODataErrorContext errorContext = providerFacade.createDeserializer(JSON).
+        readErrorDocument(StringHelper.encapsulate(errorDoc));
+    //
+    assertEquals("Wrong content type", "application/json", errorContext.getContentType());
+    assertEquals("Wrong message", "Message", errorContext.getMessage());
+    assertEquals("Wrong error code", "ErrorCode", errorContext.getErrorCode());
+    assertEquals("Wrong locale for lang", Locale.US, errorContext.getLocale());
+  }
+
+  @Test
+  public void readErrorDocumentXml() throws EntityProviderException {
+    ODataClient providerFacade = ODataClient.newInstance();
+    String errorDoc =
+        "<?xml version='1.0' encoding='UTF-8'?>\n" +
+            "<error xmlns=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\">\n" +
+            "\t<code>ErrorCode</code>\n" +
+            "\t<message xml:lang=\"en-US\">Message</message>\n" +
+            "</error>";
+    ODataErrorContext errorContext = providerFacade.createDeserializer(XML).
+        readErrorDocument(StringHelper.encapsulate(errorDoc));
+    //
+    assertEquals("Wrong content type", "application/xml", errorContext.getContentType());
+    assertEquals("Wrong message", "Message", errorContext.getMessage());
+    assertEquals("Wrong error code", "ErrorCode", errorContext.getErrorCode());
+    assertEquals("Wrong locale for lang", Locale.US, errorContext.getLocale());
+  }
+}


[24/24] olingo-odata2 git commit: [OLINGO-1253]Client Module for Olingo v2

Posted by ar...@apache.org.
[OLINGO-1253]Client Module for Olingo v2


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

Branch: refs/heads/clientModule
Commit: 9e949e40605f1528560e3bc9f1646b6686046005
Parents: 91bd4b8
Author: Archana Rai <ar...@sap.com>
Authored: Mon Apr 2 17:01:26 2018 +0530
Committer: Archana Rai <ar...@sap.com>
Committed: Mon Apr 2 17:01:26 2018 +0530

----------------------------------------------------------------------
 .../olingo/odata2/api/edm/EdmException.java     |     5 +
 .../odata2/api/ep/EntityProviderException.java  |     9 +-
 odata2-lib/odata-client-api/pom.xml             |    71 +
 .../olingo/odata2/client/api/ODataClient.java   |   119 +
 .../olingo/odata2/client/api/edm/ClientEdm.java |    41 +
 .../odata2/client/api/edm/EdmDataServices.java  |    85 +
 .../odata2/client/api/edm/EdmDocumentation.java |    58 +
 .../olingo/odata2/client/api/edm/EdmSchema.java |    81 +
 .../olingo/odata2/client/api/edm/EdmUsing.java  |    57 +
 .../api/ep/ContentTypeBasedDeserializer.java    |    91 +
 .../api/ep/ContentTypeBasedSerializer.java      |    63 +
 .../DeserializerMetadataProviderInterface.java  |    30 +
 .../client/api/ep/DeserializerProperties.java   |   170 +
 .../olingo/odata2/client/api/ep/Entity.java     |    97 +
 .../odata2/client/api/ep/EntityCollection.java  |    79 +
 .../EntityCollectionSerializerProperties.java   |   119 +
 .../api/ep/EntitySerializerProperties.java      |   159 +
 .../odata2/client/api/ep/EntityStream.java      |    55 +
 .../ep/callback/OnDeserializeInlineContent.java |    47 +
 .../odata2/client/api/uri/EdmURIBuilder.java    |   184 +
 .../odata2/client/api/uri/QueryOption.java      |    70 +
 .../odata2/client/api/uri/SegmentType.java      |    76 +
 .../odata2/client/api/uri/URIBuilder.java       |   174 +
 odata2-lib/odata-client-core/pom.xml            |    90 +
 .../odata2/client/core/ODataClientImpl.java     |   199 +
 .../core/edm/EdmMetadataAssociationEnd.java     |    38 +
 .../odata2/client/core/edm/EdmOnDelete.java     |    52 +
 .../edm/Impl/EdmAnnotationAttributeImpl.java    |    99 +
 .../core/edm/Impl/EdmAnnotationElementImpl.java |    93 +
 .../core/edm/Impl/EdmAnnotationsImpl.java       |    82 +
 .../core/edm/Impl/EdmAssociationEndImpl.java    |   106 +
 .../core/edm/Impl/EdmAssociationImpl.java       |   149 +
 .../core/edm/Impl/EdmAssociationSetEndImpl.java |    92 +
 .../core/edm/Impl/EdmAssociationSetImpl.java    |   137 +
 .../core/edm/Impl/EdmComplexPropertyImpl.java   |    56 +
 .../core/edm/Impl/EdmComplexTypeImpl.java       |    75 +
 .../Impl/EdmCustomizableFeedMappingsImpl.java   |   140 +
 .../core/edm/Impl/EdmDocumentationImpl.java     |   110 +
 .../client/core/edm/Impl/EdmElementImpl.java    |    55 +
 .../core/edm/Impl/EdmEntityContainerImpl.java   |   222 +
 .../client/core/edm/Impl/EdmEntitySetImpl.java  |   136 +
 .../client/core/edm/Impl/EdmEntityTypeImpl.java |   133 +
 .../core/edm/Impl/EdmFunctionImportImpl.java    |   179 +
 .../edm/Impl/EdmFunctionImportParameter.java    |   140 +
 .../odata2/client/core/edm/Impl/EdmImpl.java    |   207 +
 .../odata2/client/core/edm/Impl/EdmKeyImpl.java |   101 +
 .../client/core/edm/Impl/EdmMappingImpl.java    |    99 +
 .../client/core/edm/Impl/EdmNamedImpl.java      |    82 +
 .../edm/Impl/EdmNavigationPropertyImpl.java     |   119 +
 .../client/core/edm/Impl/EdmOnDeleteImpl.java   |   112 +
 .../client/core/edm/Impl/EdmParameterImpl.java  |    71 +
 .../client/core/edm/Impl/EdmPropertyImpl.java   |    91 +
 .../core/edm/Impl/EdmPropertyRefImpl.java       |    47 +
 .../edm/Impl/EdmReferentialConstraintImpl.java  |    72 +
 .../Impl/EdmReferentialConstraintRoleImpl.java  |    98 +
 .../client/core/edm/Impl/EdmSchemaImpl.java     |   205 +
 .../core/edm/Impl/EdmSimplePropertyImpl.java    |    62 +
 .../core/edm/Impl/EdmStructuralTypeImpl.java    |   154 +
 .../client/core/edm/Impl/EdmTypedImpl.java      |    84 +
 .../client/core/edm/Impl/EdmUsingImpl.java      |   129 +
 .../core/ep/AtomSerializerDeserializer.java     |   211 +
 .../core/ep/JsonSerializerDeserializer.java     |   169 +
 .../ep/deserializer/JsonEntityDeserializer.java |   218 +
 .../ep/deserializer/JsonEntryDeserializer.java  |   451 +
 .../JsonErrorDocumentDeserializer.java          |   278 +
 .../ep/deserializer/JsonFeedDeserializer.java   |   255 +
 .../deserializer/JsonPropertyDeserializer.java  |   326 +
 .../ep/deserializer/XmlEntityDeserializer.java  |   190 +
 .../ep/deserializer/XmlEntryDeserializer.java   |   596 +
 .../XmlErrorDocumentDeserializer.java           |   184 +
 .../ep/deserializer/XmlFeedDeserializer.java    |   226 +
 .../deserializer/XmlMetadataDeserializer.java   |  1570 +++
 .../deserializer/XmlPropertyDeserializer.java   |   199 +
 .../serializer/AtomEntryEntitySerializer.java   |   669 +
 .../core/ep/serializer/AtomFeedSerializer.java  |   183 +
 .../serializer/JsonEntryEntitySerializer.java   |   309 +
 .../ep/serializer/JsonFeedEntitySerializer.java |   125 +
 .../ep/serializer/JsonLinkEntitySerializer.java |    49 +
 .../JsonPropertyEntitySerializer.java           |   151 +
 .../serializer/XmlPropertyEntitySerializer.java |   234 +
 .../client/core/uri/EdmURIBuilderImpl.java      |   491 +
 .../olingo/odata2/client/core/uri/Segment.java  |    32 +
 .../odata2/client/core/uri/URIBuilderImpl.java  |   217 +
 .../odata2/client/core/uri/util/UriUtil.java    |   186 +
 .../core/edm/impl/EdmAnnotationImplTest.java    |    95 +
 .../core/edm/impl/EdmAssociationImplTest.java   |    64 +
 .../core/edm/impl/EdmDocumentationImplTest.java |    53 +
 .../client/core/edm/impl/EdmEntityImplTest.java |   215 +
 .../core/edm/impl/EdmMappingImplTest.java       |    43 +
 .../core/edm/impl/EdmOnDeleteImplTest.java      |    48 +
 .../client/core/ep/AbstractProviderTest.java    |   214 +
 .../core/ep/AbstractXmlProducerTestHelper.java  |    66 +
 .../core/ep/DeserializerPropertiesTest.java     |    65 +
 .../core/ep/JSON_XMLErrorConsumerTest.java      |    70 +
 .../ep/ProducerConsumerIntegrationTest.java     |   811 ++
 .../core/ep/SerializerPropertiesTest.java       |    87 +
 .../deserializer/AbstractDeserializerTest.java  |   182 +
 .../AbstractXmlDeserializerTest.java            |    63 +
 .../client/core/ep/deserializer/Callback.java   |    21 +
 .../JsonEntryDeepInsertEntryTest.java           |   168 +
 .../JsonEntryDeepInsertFeedTest.java            |   154 +
 .../deserializer/JsonEntryDeserializerTest.java |   539 +
 .../JsonErrorDocumentDeserializerTest.java      |   234 +
 .../deserializer/JsonFeedDeserializerTest.java  |   689 +
 .../JsonPropertyDeserializerTest.java           |   834 ++
 ...LMetadataFunctionImportDeserializerTest.java |   583 +
 .../deserializer/XmlEntityDeserializerTest.java |  2461 ++++
 .../ep/deserializer/XmlErrorDocumentTest.java   |   281 +
 .../deserializer/XmlFeedDeserializerTest.java   |   241 +
 .../XmlMetadataAssociationTest.java             |   504 +
 .../XmlMetadataDeserializerTest.java            |  1904 +++
 .../ep/serializer/AtomEntrySerializerTest.java  |  1814 +++
 .../ep/serializer/AtomFeedSerializerTest.java   |  1033 ++
 .../JsonEntryEntitySerializerTest.java          |  1027 ++
 .../JsonFeedEntitySerializerTest.java           |   919 ++
 .../client/core/uri/EdmUriBuilderTest.java      |   988 ++
 .../core/uri/UriBuilderIntegrationTest.java     |    51 +
 .../odata2/client/core/uri/UriBuilderTest.java  |   586 +
 .../odata2/client/core/uri/UriInfoTest.java     |   168 +
 .../odata2/client/core/uri/UriParserTest.java   |  1132 ++
 .../src/test/resources/EmployeeContentOnly.xml  |    37 +
 .../EmployeeContentOnlyWithNavigationLink.xml   |    38 +
 .../src/test/resources/JsonBuilding.json        |    17 +
 .../resources/JsonBuildingWithInlineRooms.json  |    37 +
 ...ldingWithInlineRoomsAndNextLinkAndCount.json |    39 +
 .../JsonBuildingWithInlineRoomsClientCase.json  |    35 +
 .../test/resources/JsonBuildingWithoutD.json    |    15 +
 .../src/test/resources/JsonEmployee.json        |    48 +
 .../test/resources/JsonEmployeeContentOnly.json |    25 +
 ...onEmployeeContentOnlyWithAdditionalLink.json |    30 +
 .../JsonEmployeeInlineRoomBuilding.json         |    75 +
 .../resources/JsonEmployeeWithInlineTeam.json   |    58 +
 .../JsonInlineRoomWithInlineBuilding.json       |    75 +
 .../resources/JsonInlineRoomWithInlineNull.json |    44 +
 .../JsonInvalidTeamDoubleNameProperty.json      |    18 +
 .../src/test/resources/JsonRoom.json            |    24 +
 .../src/test/resources/JsonRoomContentOnly.json |     8 +
 .../JsonRoomContentOnlyWithAdditionalLink.json  |    13 +
 .../JsonRoom_EmptyInlineEmployeesToTeam.json    |    22 +
 .../JsonRoom_InlineEmployeesToTeam.json         |    79 +
 .../JsonRoomsToEmployeesWithInlineTeams.json    |   118 +
 .../JsonRooms_InlineEmployeesTeams.json         |   236 +
 ...sonRooms_InlineEmployees_InlineBuilding.json |   236 +
 .../src/test/resources/JsonTeam.json            |    17 +
 .../src/test/resources/JsonTeams.json           |    34 +
 .../src/test/resources/JsonTeamsWithCount.json  |    35 +
 .../resources/JsonTeamsWithCountWithoutD.json   |    34 +
 .../resources/JsonTeamsWithInlineEmployees.json |   151 +
 .../src/test/resources/JsonTeamsWithoutD.json   |    33 +
 .../test/resources/JsonWithDeletedEntries.json  |    30 +
 .../src/test/resources/LargeEmployeeFeed.xml    | 12556 +++++++++++++++++
 .../src/test/resources/ProductsFeed.xml         |   474 +
 .../src/test/resources/RoomContentOnly.xml      |    28 +
 .../RoomContentOnlyWithNavigationLink.xml       |    29 +
 .../RoomsToEmployeesWithInlineTeams.xml         |   104 +
 .../src/test/resources/batchWithPost.batch      |    39 +
 .../src/test/resources/double_expanded_team.xml |   264 +
 .../src/test/resources/expandedBuilding.xml     |    61 +
 .../src/test/resources/expanded_team.xml        |   146 +
 .../src/test/resources/feed_employees.xml       |   247 +
 .../src/test/resources/feed_employees_full.xml  |   249 +
 .../resources/feed_with_deleted_entries.xml     |    40 +
 .../src/test/resources/feed_with_delta_link.xml |    69 +
 .../test/resources/metadataForDeepInsert.xml    |    53 +
 .../test/resources/metadataForRelatedEntity.xml |   240 +
 .../src/test/resources/metadataProducts.xml     |    69 +
 .../test/resources/metadataWithNavigations.xml  |    19 +
 .../olingo/odata2/core/uri/UriParserImpl.java   |     1 +
 .../src/main/resources/i18n.properties          |     7 +-
 .../olingo/odata2/testutil/mock/EdmMock.java    |    40 +-
 odata2-lib/pom.xml                              |     4 +-
 171 files changed, 48377 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmException.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmException.java b/odata2-lib/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmException.java
index bc43ac8..c3236c2 100644
--- a/odata2-lib/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmException.java
+++ b/odata2-lib/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmException.java
@@ -31,6 +31,9 @@ public class EdmException extends ODataMessageException {
   private static final long serialVersionUID = 1L;
 
   public static final MessageReference COMMON = createMessageReference(EdmException.class, "COMMON");
+  public static final MessageReference TYPEPROBLEM = createMessageReference(EdmException.class, "TYPEPROBLEM");
+  public static final MessageReference ENTITYTYPEPROBLEM = 
+      createMessageReference(EdmException.class, "ENTITYTYPEPROBLEM");
   public static final MessageReference PROVIDERPROBLEM = createMessageReference(EdmException.class, "PROVIDERPROBLEM");
   public static final MessageReference PROPERTYNOTFOUND =
       createMessageReference(EdmException.class, "PROPERTYNOTFOUND");
@@ -41,6 +44,8 @@ public class EdmException extends ODataMessageException {
   public static final MessageReference MUSTBEPROPERTY = createMessageReference(EdmException.class, "MUSTBEPROPERTY");
   public static final MessageReference NAMINGERROR =
       createMessageReference(EdmException.class, "NAMINGERROR");
+  public static final MessageReference ASSOCIATIONNOTFOUND =
+      createMessageReference(EdmException.class, "ASSOCIATIONNOTFOUND");
   
   public EdmException(final MessageReference messageReference) {
     super(messageReference);

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/EntityProviderException.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/EntityProviderException.java b/odata2-lib/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/EntityProviderException.java
index 4c157a9..b6c5df7 100644
--- a/odata2-lib/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/EntityProviderException.java
+++ b/odata2-lib/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/EntityProviderException.java
@@ -102,9 +102,16 @@ public class EntityProviderException extends ODataMessageException {
   /** MISSING_RESULTS_ARRAY requires no content value */
   public static final MessageReference MISSING_RESULTS_ARRAY = createMessageReference(EntityProviderException.class,
       "MISSING_RESULTS_ARRAY");
-
+  public static final MessageReference NULL_VALUE = createMessageReference(EntityProviderException.class, 
+      "NULL_VALUE");
   public static final MessageReference INVALID_DELETED_ENTRY_METADATA = createMessageReference(
       EntityProviderException.class, "INVALID_DELETED_ENTRY_METADATA");
+  /** Navigation Property has incorrect type */
+  public static final MessageReference INCORRECT_NAVIGATION_TYPE = createMessageReference(
+      EntityProviderException.class, "INCORRECT_NAVIGATION_TYPE");
+  /** MANDATORY_WRITE_PROPERTY requires no content value */
+  public static final MessageReference MANDATORY_WRITE_PROPERTY = createMessageReference(EntityProviderException.class, 
+    "MANDATORY_WRITE_PROPERTY");
 
   public EntityProviderException(final MessageReference messageReference) {
     super(messageReference);

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-api/pom.xml
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-api/pom.xml b/odata2-lib/odata-client-api/pom.xml
new file mode 100644
index 0000000..4291bec
--- /dev/null
+++ b/odata2-lib/odata-client-api/pom.xml
@@ -0,0 +1,71 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+
+	<parent>
+		<groupId>org.apache.olingo</groupId>
+		<artifactId>olingo-odata2-lib</artifactId>
+		<version>2.0.11-SNAPSHOT</version>
+		<relativePath>..</relativePath>
+	</parent>
+	<artifactId>olingo-odata2-client-api</artifactId>
+	<packaging>jar</packaging>
+	<name>${project.artifactId}</name>
+
+	<dependencies>
+		<dependency>
+			<groupId>junit</groupId>
+			<artifactId>junit</artifactId>
+			<version>${junit.version}</version>
+		</dependency>
+		
+		<dependency>
+			<groupId>org.apache.olingo</groupId>
+			<artifactId>olingo-odata2-api</artifactId>
+			<version>${project.version}</version>
+		</dependency> 
+		
+			
+	</dependencies>
+	<build>
+		<plugins>
+			<plugin>
+				<artifactId>maven-jar-plugin</artifactId>
+				<configuration>
+					<archive>
+						<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
+					</archive>
+				</configuration>
+			</plugin>
+			<plugin>
+				<groupId>org.apache.felix</groupId>
+				<artifactId>maven-bundle-plugin</artifactId>
+				<extensions>true</extensions>
+				<executions>
+					<execution>
+						<id>bundle-manifest</id>
+						<phase>process-classes</phase>
+						<goals>
+							<goal>manifest</goal>
+						</goals>
+					</execution>
+				</executions>
+				<configuration>
+					<instructions>
+						<Import-Package>
+							org.apache.olingo.odata2.client.core.ep;resolution:=optional,
+							*
+						</Import-Package>
+						<Export-Package>
+							org.apache.olingo.odata2.client.api;version=${project.version},
+							org.apache.olingo.odata2.client.api.*;version=${project.version}
+						</Export-Package>
+						<Bundle-DocURL>${project.url}</Bundle-DocURL>
+						<Bundle-ActivationPolicy>lazy</Bundle-ActivationPolicy>
+						<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
+					</instructions>
+				</configuration>
+			</plugin>
+		</plugins>
+	</build>
+</project>

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/ODataClient.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/ODataClient.java b/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/ODataClient.java
new file mode 100644
index 0000000..f031004
--- /dev/null
+++ b/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/ODataClient.java
@@ -0,0 +1,119 @@
+package org.apache.olingo.odata2.client.api;
+
+import java.io.InputStream;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.exception.ODataRuntimeApplicationException;
+import org.apache.olingo.odata2.api.uri.PathSegment;
+import org.apache.olingo.odata2.api.uri.UriInfo;
+import org.apache.olingo.odata2.api.uri.UriNotMatchingException;
+import org.apache.olingo.odata2.api.uri.UriSyntaxException;
+import org.apache.olingo.odata2.client.api.edm.EdmDataServices;
+import org.apache.olingo.odata2.client.api.ep.ContentTypeBasedDeserializer;
+import org.apache.olingo.odata2.client.api.ep.ContentTypeBasedSerializer;
+import org.apache.olingo.odata2.client.api.uri.EdmURIBuilder;
+import org.apache.olingo.odata2.client.api.uri.URIBuilder;
+
+/**
+ * This class provides an instance of odata Client
+ *
+ */
+public abstract class ODataClient {
+  
+  private static final String IMPLEMENTATION = "org.apache.olingo.odata2.client.core.ODataClientImpl";
+
+  /**
+   * Use this method to create a new OData instance. Each thread/request should keep its own instance.
+   * @return a new OData instance
+   */
+  public static ODataClient newInstance() {
+    try {
+      final Class<?> clazz = Class.forName(ODataClient.IMPLEMENTATION);
+
+      /*
+       * We explicitly do not use the singleton pattern to keep the server state free
+       * and avoid class loading issues also during hot deployment.
+       */
+      final Object object = clazz.newInstance();
+
+      return (ODataClient) object;
+
+    } catch (final Exception e) {
+      //TODO: Change the exception
+      throw new ODataRuntimeApplicationException(null, null, null, null, e);
+    }
+  }
+  
+  /**
+   * Creates a new serializer object for rendering content in the specified format.
+   * 
+   * @param contentType any format supported by Olingo (XML, JSON ...)
+   * @return ContentTypeBasedSerializer
+   */
+  public abstract ContentTypeBasedSerializer createSerializer(String contentType) throws EntityProviderException;
+
+  /**
+   * Creates a new deserializer object for reading content in the specified format.
+   * 
+   * @param contentType any content type supported by Olingo (XML, JSON ...)
+   * @return ContentTypeBasedDeserializer
+   */
+  public abstract ContentTypeBasedDeserializer createDeserializer(String contentType) throws EntityProviderException;
+  
+  /**
+   * Reads the metadata file and validates it if validate parameter is set to true
+   * @param content inputStream
+   * @param validate
+   * @return EdmDataServices
+   * @throws EntityProviderException
+   */
+  public abstract EdmDataServices readMetadata(InputStream content, boolean validate) 
+      throws EntityProviderException, EdmException;  //NOPMD  - suppressed
+  
+  /**
+   * Parses the uri and returns UriInfo
+   * @param edm
+   * @param pathSegments
+   * @param queryParameters
+   * @return UriInfo
+   * @throws EntityProviderException
+   * @throws EdmException
+   */
+  
+  public abstract UriInfo parseUri(final Edm edm, final List<PathSegment> pathSegments, 
+      final Map<String, List<String>> queryParameters) 
+      throws UriSyntaxException, UriNotMatchingException, EdmException; //NOPMD  - suppressed
+  
+  /**
+   * Parses the uri and returns UriInfo
+   * @param edm
+   * @param uri
+   * @return UriInfo
+   * @throws UriSyntaxException
+   * @throws UriNotMatchingException
+   * @throws EdmException
+   */
+  
+  public abstract UriInfo parseUri(final Edm edm, final String uri) 
+      throws UriSyntaxException, UriNotMatchingException, EdmException; //NOPMD  - suppressed
+   
+  
+  
+  /**
+   * Constructs the edm uri based on segments appended
+   * @param serviceRoot
+   * @return EdmURIBuilder
+   */
+  public abstract EdmURIBuilder edmUriBuilder(String serviceRoot);
+  
+  /**
+   * Constructs the uri based on segments appended
+   * @param serviceRoot
+   * @return URIBuilder
+   */
+  public abstract URIBuilder uriBuilder(String serviceRoot);
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/edm/ClientEdm.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/edm/ClientEdm.java b/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/edm/ClientEdm.java
new file mode 100644
index 0000000..6113fd7
--- /dev/null
+++ b/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/edm/ClientEdm.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * 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.client.api.edm;
+
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+
+/**
+ * @org.apache.olingo.odata2.DoNotImplement
+ * Entity Data Model (EDM)
+ * <p>Interface representing a Entity Data Model as described in the Conceptual Schema Definition.
+ * 
+ */
+public interface ClientEdm extends Edm{
+
+  /**
+   * This method <b>DOES NOT</b> support lazy loading. All schemas are loaded completely!
+   *
+   * @return all schemas defined for this EDM
+   */
+  List<EdmSchema> getSchemas();
+
+  
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/edm/EdmDataServices.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/edm/EdmDataServices.java b/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/edm/EdmDataServices.java
new file mode 100644
index 0000000..056eb1e
--- /dev/null
+++ b/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/edm/EdmDataServices.java
@@ -0,0 +1,85 @@
+/*******************************************************************************
+ * 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.client.api.edm;
+
+/**
+ * Objects of this class represent the data service. They contain all schemas of the EDM as well as the
+ * dataServiceVersion
+ * 
+ */
+public class EdmDataServices {
+
+  private ClientEdm edm;
+  private String dataServiceVersion;
+  private String customEdmxVersion;
+
+ 
+  /**
+   * Sets the Edm for this {@link EdmDataServices}
+   * @param edm
+   * @return {@link EdmDataServices} for method chaining
+   */
+  public EdmDataServices setClientEdm(final ClientEdm edm) {
+    this.edm = edm;
+    return this;
+  }
+
+
+  /**
+   * Sets the data service version for this {@link EdmDataServices}
+   * @param dataServiceVersion
+   * @return {@link EdmDataServices} for method chaining
+   */
+  public EdmDataServices setDataServiceVersion(final String dataServiceVersion) {
+    this.dataServiceVersion = dataServiceVersion;
+    return this;
+  }
+
+  
+  /**
+   * Sets a custom edmx version which is used in the metadata document
+   * @param customEdmxVersion
+   * @return {@link ComplexType} for method chaining
+   */
+  public EdmDataServices setCustomEdmxVersion(String customEdmxVersion) {
+    this.customEdmxVersion = customEdmxVersion;
+    return this;
+  }
+
+  /**
+   * @return <b>String</b> data service version
+   */
+  public String getDataServiceVersion() {
+    return dataServiceVersion;
+  }
+
+  /**
+   * @return <b>String</b> custom edmx version
+   */
+  public String getCustomEdmxVersion() {
+    return customEdmxVersion;
+  }
+  
+  /**
+   * @return <b>Edm</b> edm
+   */
+  public ClientEdm getEdm() {
+    return edm;
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/edm/EdmDocumentation.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/edm/EdmDocumentation.java b/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/edm/EdmDocumentation.java
new file mode 100644
index 0000000..1df22d1
--- /dev/null
+++ b/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/edm/EdmDocumentation.java
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * 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.client.api.edm;
+
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.EdmAnnotationAttribute;
+import org.apache.olingo.odata2.api.edm.EdmAnnotationElement;
+
+/**
+ * Objects of this class represent documentation
+ * 
+ */
+public interface EdmDocumentation {
+
+  /**
+   * Sets the summary for this {@link EdmDocumentation}
+   * @param summary
+   * @return {@link EdmDocumentation} for method chaining
+   */
+  public EdmDocumentation setSummary(final String summary);
+
+  /**
+   * Sets the long description for this {@link EdmDocumentation}
+   * @param longDescription
+   * @return {@link EdmDocumentation} for method chaining
+   */
+  public EdmDocumentation setLongDescription(final String longDescription) ;
+  /**
+   * Sets the collection of {@link AnnotationAttribute} for this {@link EdmDocumentation}
+   * @param annotationAttributes
+   * @return {@link EdmDocumentation} for method chaining
+   */
+  public EdmDocumentation setAnnotationAttributes(final List<EdmAnnotationAttribute> annotationAttributes) ;
+
+  /**
+   * Sets the collection of {@link AnnotationElement} for this {@link EdmDocumentation}
+   * @param annotationElements
+   * @return {@link EdmDocumentation} for method chaining
+   */
+  public EdmDocumentation setAnnotationElements(final List<EdmAnnotationElement> annotationElements);
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/edm/EdmSchema.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/edm/EdmSchema.java b/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/edm/EdmSchema.java
new file mode 100644
index 0000000..5d3cd1e
--- /dev/null
+++ b/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/edm/EdmSchema.java
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * 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.client.api.edm;
+
+import java.util.List;
+import org.apache.olingo.odata2.api.edm.provider.Using;
+import org.apache.olingo.odata2.api.edm.EdmEntityType;
+import org.apache.olingo.odata2.api.edm.EdmEntityContainer;
+import org.apache.olingo.odata2.api.edm.EdmAssociation;
+import org.apache.olingo.odata2.api.edm.EdmComplexType;
+import org.apache.olingo.odata2.api.edm.EdmAnnotationAttribute;
+import org.apache.olingo.odata2.api.edm.EdmAnnotationElement;
+
+/**
+ * Impl Objects of this class represent a client schema
+ * 
+ */
+public interface EdmSchema { 
+
+  /**
+   * @return <b>String</b> namespace of this {@link EdmSchema}
+   */
+  public String getNamespace() ;
+
+  /**
+   * @return <b>String</b> alias of this {@link EdmSchema}
+   */
+  public String getAlias() ;
+
+  /**
+   * @return List<{@link Using}> of this {@link EdmSchema}
+   */
+  public List<EdmUsing> getUsings() ;
+
+  /**
+   * @return List<{@link EntityType}> of this {@link EdmSchema}
+   */
+  public List<EdmEntityType> getEntityTypes() ;
+  
+
+  /**
+   * @return List<{@link ComplexType}> of this {@link EdmSchema}
+   */
+  public List<EdmComplexType> getComplexTypes() ;
+
+  /**
+   * @return List<{@link Association}> of this {@link EdmSchema}
+   */
+  public List<EdmAssociation> getAssociations() ;
+
+  /**
+   * @return List<{@link EntityContainer}> of this {@link EdmSchema}
+   */
+  public List<EdmEntityContainer> getEntityContainers(); 
+
+  /**
+   * @return List of {@link AnnotationAttribute} annotation attributes
+   */
+  public List<EdmAnnotationAttribute> getAnnotationAttributes();
+
+  /**
+   * @return List of {@link AnnotationElement} annotation elements
+   */
+  public List<EdmAnnotationElement> getAnnotationElements() ;
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/edm/EdmUsing.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/edm/EdmUsing.java b/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/edm/EdmUsing.java
new file mode 100644
index 0000000..df42d5e
--- /dev/null
+++ b/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/edm/EdmUsing.java
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * 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.client.api.edm;
+
+import java.util.Collection;
+
+import org.apache.olingo.odata2.api.edm.EdmAnnotationAttribute;
+import org.apache.olingo.odata2.api.edm.EdmAnnotationElement;
+import org.apache.olingo.odata2.api.edm.provider.AnnotationAttribute;
+import org.apache.olingo.odata2.api.edm.provider.AnnotationElement;
+
+/**
+ *  Impl objects of this class create a client EdmUsing
+ */
+public interface EdmUsing {
+
+  /**
+   * @return <b>String</b> namespace
+   */
+  public String getNamespace() ;
+
+  /**
+   * @return <b>String</b> alias
+   */
+  public String getAlias() ;
+
+  /**
+   * @return {@link EdmDocumentation} documentation
+   */
+  public EdmDocumentation getDocumentation() ;
+
+  /**
+   * @return collection of {@link AnnotationAttribute} annotation attributes
+   */
+  public Collection<EdmAnnotationAttribute> getAnnotationAttributes() ;
+
+  /**
+   * @return collection of {@link AnnotationElement} annotation elements
+   */
+  public Collection<EdmAnnotationElement> getAnnotationElements() ;
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/ep/ContentTypeBasedDeserializer.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/ep/ContentTypeBasedDeserializer.java b/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/ep/ContentTypeBasedDeserializer.java
new file mode 100644
index 0000000..4036cbf
--- /dev/null
+++ b/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/ep/ContentTypeBasedDeserializer.java
@@ -0,0 +1,91 @@
+/*******************************************************************************
+ * 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.client.api.ep;
+
+import java.io.InputStream;
+import java.util.List;
+
+import org.apache.olingo.odata2.api.batch.BatchException;
+import org.apache.olingo.odata2.api.batch.BatchResponsePart;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmFunctionImport;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.ep.entry.ODataEntry;
+import org.apache.olingo.odata2.api.ep.feed.ODataFeed;
+import org.apache.olingo.odata2.api.processor.ODataErrorContext;
+import org.apache.olingo.odata2.api.processor.ODataResponse;
+
+/**
+ * Interface for all none basic (content type <b>dependent</b>) deserializer methods.
+ * 
+ * 
+ */
+public interface ContentTypeBasedDeserializer {
+
+  /**
+   * Returns an ODataFeed
+   * @param entitySet
+   * @param content
+   * @return ODataFeed
+   * @throws EntityProviderException
+   */
+  ODataFeed readFeed(EdmEntitySet entitySet, EntityStream content)
+      throws EntityProviderException;
+
+  /**
+   * Returns an ODataEntry
+   * @param entitySet
+   * @param content
+   * @return ODataEntry
+   * @throws EntityProviderException
+   */
+  ODataEntry readEntry(EdmEntitySet entitySet, EntityStream content)
+      throws EntityProviderException;
+
+  /**
+   * Read (de-serialize) data from error document as {@link InputStream} and provide according
+   * {@link ODataErrorContext}.
+   * 
+   * @param errorDocument error document which is read
+   * @param contentType format of content in the given input stream
+   * @return read error document
+   * @throws EntityProviderException if reading of data (de-serialization) fails
+   */
+  ODataErrorContext readErrorDocument(InputStream errorDocument) throws EntityProviderException;
+
+  /**
+   * Returns an ODataResponse
+   * @param batchResponseParts
+   * @return ODataResponse
+   * @throws BatchException
+   */
+  ODataResponse writeBatchResponse(final List<BatchResponsePart> batchResponseParts) 
+      throws BatchException;
+  
+  /**
+   * Returns an object
+   * @param functionImport
+   * @param content
+   * @return
+   * @throws EntityProviderException
+   */
+  Object readFunctionImport(final EdmFunctionImport functionImport, 
+      final EntityStream content) throws EntityProviderException;
+  
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/ep/ContentTypeBasedSerializer.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/ep/ContentTypeBasedSerializer.java b/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/ep/ContentTypeBasedSerializer.java
new file mode 100644
index 0000000..1b4bbee
--- /dev/null
+++ b/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/ep/ContentTypeBasedSerializer.java
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * 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.client.api.ep;
+
+import java.io.InputStream;
+import java.util.List;
+
+import org.apache.olingo.odata2.api.client.batch.BatchPart;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.processor.ODataResponse;
+
+/**
+ * Interface for all none basic (content type <b>dependent</b>) serializer methods.
+ * 
+ * 
+ */
+public interface ContentTypeBasedSerializer {
+
+  /**
+   * Returns an OData Response for a given entry
+   * @param entitySet
+   * @param data
+   * @return ODataResponse
+   * @throws EntityProviderException
+   */
+  ODataResponse writeEntry(EdmEntitySet entitySet, Entity data)
+      throws EntityProviderException;
+  
+  /**
+   * Returns an OData Response for a given feed
+   * @param entitySet
+   * @param data
+   * @return ODataResponse
+   * @throws EntityProviderException
+   */
+  ODataResponse writeFeed(EdmEntitySet entitySet, EntityCollection data)
+      throws EntityProviderException;
+  
+  /**
+   * Reads Batch Request Parts and returns an input Stream
+   * @param batchParts
+   * @param boundary
+   * @return InputStream
+   */
+  InputStream readBatchRequest(final List<BatchPart> batchParts, final String boundary);
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/ep/DeserializerMetadataProviderInterface.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/ep/DeserializerMetadataProviderInterface.java b/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/ep/DeserializerMetadataProviderInterface.java
new file mode 100644
index 0000000..3ddf338
--- /dev/null
+++ b/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/ep/DeserializerMetadataProviderInterface.java
@@ -0,0 +1,30 @@
+package org.apache.olingo.odata2.client.api.ep;
+
+import java.io.InputStream;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.client.api.edm.EdmDataServices;
+
+/**
+ * 
+ * Interface for metadata deserializer methods.
+ *
+ */
+public interface DeserializerMetadataProviderInterface {
+
+
+  /**
+   * Read (de-serialize) data from metadata <code>inputStream</code> (as {@link InputStream}) and provide Edm as
+   * {@link Edm}
+   * 
+   * @param inputStream the given input stream
+   * @param validate has to be true if metadata should be validated
+   * @return Edm as {@link Edm}
+   * @throws EntityProviderException, EdmException if reading of data (de-serialization) fails
+   */
+  EdmDataServices readMetadata(InputStream content, boolean validate) 
+      throws EntityProviderException, EdmException; //NOPMD  - suppressed
+
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/ep/DeserializerProperties.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/ep/DeserializerProperties.java b/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/ep/DeserializerProperties.java
new file mode 100644
index 0000000..c1ef36f
--- /dev/null
+++ b/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/ep/DeserializerProperties.java
@@ -0,0 +1,170 @@
+/*******************************************************************************
+ * 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.client.api.ep;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.ep.EntityProvider;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.ep.EntityProviderReadProperties;
+import org.apache.olingo.odata2.client.api.ep.callback.OnDeserializeInlineContent;
+
+/**
+ * <p>The {@link EntityProviderReadProperties} contains all necessary settings
+ * to read an entity with the {@link EntityProvider}.</p>
+ * <p>The main settings are
+ * <ul>
+ * <li>the <code>type mappings</code></li>
+ * <li>and <code>validatingFacets</code></li>
+ * </ul>
+ * </p>
+ */
+public class DeserializerProperties{
+  /** Callback which is necessary if entity contains inlined navigation properties. */
+  private OnDeserializeInlineContent callback;
+  /**
+   * typeMappings contains mappings from <code>edm property name</code> to <code>java class</code> which should be used
+   * for a type mapping during reading of content. If according <code>edm property</code> can not be read
+   * into given <code>java class</code> an {@link EntityProviderException} is thrown.
+   * Supported mappings are documented in {@link org.apache.olingo.odata2.api.edm.EdmSimpleType}.
+   */
+  private final Map<String, Object> typeMappings;//entity
+  
+  /** whether the constraints expressed in properties' facets are validated */
+  private boolean validatingFacets = true;//entity
+
+  private final Map<String, String> validatedPrefix2NamespaceUri;//Collection
+
+  private DeserializerProperties() {
+    typeMappings = new HashMap<String, Object>();
+    validatedPrefix2NamespaceUri = new HashMap<String, String>();
+  }
+
+  /**
+   * 
+   * @return DeserializerPropertiesBuilder
+   */
+  public static DeserializerPropertiesBuilder init() {
+    return new DeserializerPropertiesBuilder();
+  }
+
+  /**
+   * 
+   * @param properties
+   * @return DeserializerPropertiesBuilder
+   */
+  public static DeserializerPropertiesBuilder initFrom
+  (final DeserializerProperties properties) {
+    return new DeserializerPropertiesBuilder(properties);
+  }
+  /**
+   * 
+   * @return TypeMappings
+   */
+  public Map<String, Object> getTypeMappings() {
+    return Collections.unmodifiableMap(typeMappings);
+  }
+
+  public Map<String, String> getValidatedPrefixNamespaceUris() {
+    return Collections.unmodifiableMap(validatedPrefix2NamespaceUri);
+  }
+
+
+  public boolean isValidatingFacets() {
+    return validatingFacets;
+  }
+  
+  public OnDeserializeInlineContent getCallback() {
+    return callback;
+  }
+
+  /**
+   * Builder for {@link EntityProviderReadProperties}.
+   */
+  public static class DeserializerPropertiesBuilder {
+    private final DeserializerProperties properties = new DeserializerProperties();
+
+    public DeserializerPropertiesBuilder() {}
+    /**
+     * 
+     * @param propertiesFrom
+     */
+    public DeserializerPropertiesBuilder(final DeserializerProperties propertiesFrom) {
+      addValidatedPrefixes(propertiesFrom.validatedPrefix2NamespaceUri);
+      addTypeMappings(propertiesFrom.typeMappings);
+      properties.validatingFacets = propertiesFrom.validatingFacets;
+      properties.callback = propertiesFrom.callback;
+    }
+
+    /**
+     * 
+     * @param prefix2NamespaceUri
+     * @return DeserializerPropertiesBuilder
+     */
+    public DeserializerPropertiesBuilder addValidatedPrefixes
+    (final Map<String, String> prefix2NamespaceUri) {
+      if (prefix2NamespaceUri != null) {
+        properties.validatedPrefix2NamespaceUri.putAll(prefix2NamespaceUri);
+      }
+      return this;
+    }
+
+    /**
+     * 
+     * @param typeMappings
+     * @return DeserializerPropertiesBuilder
+     */
+    public DeserializerPropertiesBuilder addTypeMappings(final Map<String, Object> typeMappings) {
+      if (typeMappings != null) {
+        properties.typeMappings.putAll(typeMappings);
+      }
+      return this;
+    }
+    
+    /**
+     * 
+     * @param callback
+     * @return DeserializerPropertiesBuilder
+     */
+    public DeserializerPropertiesBuilder callback(final OnDeserializeInlineContent callback) {
+      properties.callback = callback;
+      return this;
+    }
+
+    /**
+     * 
+     * @param validatingFacets
+     * @return DeserializerPropertiesBuilder
+     */
+    public DeserializerPropertiesBuilder isValidatingFacets(final boolean validatingFacets) {
+      properties.validatingFacets = validatingFacets;
+      return this;
+    }
+
+    /**
+     * 
+     * @return DeserializerProperties
+     */
+    public DeserializerProperties build() {
+      return properties;
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/ep/Entity.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/ep/Entity.java b/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/ep/Entity.java
new file mode 100644
index 0000000..a78d871
--- /dev/null
+++ b/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/ep/Entity.java
@@ -0,0 +1,97 @@
+/*
+ * 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.client.api.ep;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Data representation for a single entity.
+ */
+public class Entity {
+
+  private final Map<String, Object> properties = new HashMap<String, Object>();
+  private final Map<String, Object> navigations = new HashMap<String, Object>();
+  private EntitySerializerProperties writeProperties;
+ 
+  public Map<String, Object> getNavigations() {
+    return navigations;
+  }
+  
+  /**
+   * Add Navigation
+   * @param link
+   * @param value
+   */
+  public void addNavigation(final String link, final Object value) {
+    navigations.put(link, value);
+  }
+
+  /**
+   * 
+   * @param link
+   * @return Object
+   */
+  public Object getNavigation(String link) {
+    return navigations.get(link);
+  }
+ 
+  /**
+   * Return properties of an entity
+   * @return Properties
+   */
+  public Map<String, Object> getProperties() {
+    return properties;
+  }
+  
+  /**
+   * Add a property to entity
+   * @param property
+   * @param value
+   */
+  public void addProperty(final String property, final Object value) {
+    properties.put(property, value);
+  }
+
+  /**
+   * Get Property of an entity
+   * @param property
+   * @return Object
+   */
+  public Object getProperty(String property) {
+    return properties.get(property);
+  }
+
+  /**
+   * Returns the Write properties
+   * @return EntitySerializerProperties
+   */
+  public EntitySerializerProperties getWriteProperties() {
+    return writeProperties;
+  }
+
+  /**
+   * Sets the write properties for an entity
+   * @param writeProperties
+   */
+  public void setWriteProperties(EntitySerializerProperties writeProperties) {
+    this.writeProperties = writeProperties;
+  }
+  
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/ep/EntityCollection.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/ep/EntityCollection.java b/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/ep/EntityCollection.java
new file mode 100644
index 0000000..6846310
--- /dev/null
+++ b/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/ep/EntityCollection.java
@@ -0,0 +1,79 @@
+/*
+ * 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.client.api.ep;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Data representation for a single entity.
+ */
+public class EntityCollection {
+
+  private final List<Entity> entities = new ArrayList<Entity>();
+  private EntityCollectionSerializerProperties collectionProperties;
+  private EntitySerializerProperties globalEntityProperties;
+ 
+  /**
+   * @return the globalWriteProperties
+   */
+  public EntitySerializerProperties getGlobalEntityProperties() {
+    return globalEntityProperties;
+  }
+
+  /**
+   * @param globalWriteProperties the globalWriteProperties to set
+   */
+  public void setGlobalEntityProperties(EntitySerializerProperties globalEntityProperties) {
+    this.globalEntityProperties = globalEntityProperties;
+  }
+
+  /**
+   * 
+   * @return List of Entities
+   */
+  public List<Entity> getEntities() {
+    return entities;
+  }
+  
+  /**
+   * Add an Entity to collection of entities
+   * @param entity
+   */
+  public void addEntity(Entity entity) {
+    entities.add(entity);
+  }
+
+  /**
+   * Return collection write properties
+   * @return EntityCollectionSerializerProperties
+   */
+  public EntityCollectionSerializerProperties getCollectionProperties() {
+    return collectionProperties;
+  }
+
+  /**
+   * Set collection write properties
+   * @param collectionProperties
+   */
+  public void setCollectionProperties(EntityCollectionSerializerProperties collectionProperties) {
+    this.collectionProperties = collectionProperties;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/ep/EntityCollectionSerializerProperties.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/ep/EntityCollectionSerializerProperties.java b/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/ep/EntityCollectionSerializerProperties.java
new file mode 100644
index 0000000..cf112a6
--- /dev/null
+++ b/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/ep/EntityCollectionSerializerProperties.java
@@ -0,0 +1,119 @@
+/*******************************************************************************
+ * 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.client.api.ep;
+
+import java.net.URI;
+
+/**
+ * {@link EntityCollectionSerializerProperties} contains all additional properties which are necessary to <b>write
+ * (serialize)</b> an {@link org.apache.olingo.odata2.api.ep.entry.ODataEntry} into an specific format (e.g.
+ * <code>XML</code> or <code>JSON</code> or ...).
+ */
+public class EntityCollectionSerializerProperties {
+
+  private URI serviceRoot;
+  private URI selfLink;
+  
+  private EntityCollectionSerializerProperties() {}
+  
+  /**
+   * Gets the self link from an application. May be null.
+   * @return the self link
+   */
+  public final URI getSelfLink() {
+    return selfLink;
+  }
+
+  /**
+   * Gets the service root.
+   * @return the service root
+   */
+  public final URI getServiceRoot() {
+    return serviceRoot;
+  }
+
+  /**
+   * 
+   * @param serviceRoot
+   * @return EntityCollectionPropertiesBuilder
+   */
+  public static EntityCollectionPropertiesBuilder serviceRoot(final URI serviceRoot) {
+    return new EntityCollectionPropertiesBuilder().serviceRoot(serviceRoot);
+  }
+
+  /**
+   * This class builds the Entity collection properties
+   *
+   */
+  public static class EntityCollectionPropertiesBuilder {
+    private final EntityCollectionSerializerProperties properties = 
+        new EntityCollectionSerializerProperties();
+
+    /**
+     * @param serviceRoot
+     */
+    public final EntityCollectionPropertiesBuilder serviceRoot(final URI serviceRoot) {
+      properties.serviceRoot = serviceRoot;
+      return this;
+    }
+
+
+    /**
+     * Build properties object.
+     * @return assembled properties object
+     */
+    public final EntityCollectionSerializerProperties build() {
+      return properties;
+    }
+
+    /**
+     * 
+     * @param selfLink
+     * @return EntityCollectionPropertiesBuilder
+     */
+    public EntityCollectionPropertiesBuilder selfLink(final URI selfLink) {
+      properties.selfLink = selfLink;
+      return this;
+    }
+
+    /**
+     * 
+     * @param properties
+     * @return EntityCollectionPropertiesBuilder
+     */
+    public EntityCollectionPropertiesBuilder fromProperties
+    (final EntityCollectionSerializerProperties properties) {
+      this.properties.selfLink = properties.getSelfLink();
+      return this;
+    }
+
+  }
+
+  /**
+   * 
+   * @param properties
+   * @return EntityCollectionPropertiesBuilder
+   */
+  public static EntityCollectionPropertiesBuilder fromProperties
+  (final EntityCollectionSerializerProperties properties) {
+    final EntityCollectionPropertiesBuilder builder =
+        EntityCollectionSerializerProperties.serviceRoot(properties.getServiceRoot());
+    return builder.fromProperties(properties);
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/ep/EntitySerializerProperties.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/ep/EntitySerializerProperties.java b/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/ep/EntitySerializerProperties.java
new file mode 100644
index 0000000..c285290
--- /dev/null
+++ b/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/ep/EntitySerializerProperties.java
@@ -0,0 +1,159 @@
+/*******************************************************************************
+ * 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.client.api.ep;
+
+import java.net.URI;
+
+/**
+ * {@link EntitySerializerProperties} contains all additional properties which are necessary to <b>write
+ * (serialize)</b> an {@link org.apache.olingo.odata2.api.ep.entry.ODataEntry} into an specific format (e.g.
+ * <code>XML</code> or <code>JSON</code> or ...).
+ */
+public class EntitySerializerProperties {
+
+  private URI serviceRoot;
+  private boolean includeMetadata = false;
+  private boolean validatingFacets = true;
+  private boolean isKeyAutoGenerated = false;
+  
+  private EntitySerializerProperties() {}
+  
+  /**
+   * Set true or false to include metadata
+   * @return boolean
+   */
+  public boolean isIncludeMetadata() {
+    return includeMetadata;
+  }
+
+  /**
+   * Set true or false for auto key generation
+   * @return boolean
+   */
+  public final boolean isKeyAutoGenerated() {
+    return isKeyAutoGenerated;
+  }
+
+  /**
+   * Gets the service root.
+   * @return the service root
+   */
+  public final URI getServiceRoot() {
+    return serviceRoot;
+  }
+
+  /**
+   * 
+   * @param serviceRoot
+   * @return EntitySerializerPropertiesBuilder
+   */
+  public static EntitySerializerPropertiesBuilder serviceRoot(final URI serviceRoot) {
+    return new EntitySerializerPropertiesBuilder().serviceRoot(serviceRoot);
+  }
+
+  /**
+   * 
+   * @return boolean
+   */
+  public boolean isValidatingFacets() {
+    return validatingFacets;
+  }
+
+  /**
+   * This class builds the Entity Serializer Properties
+   *
+   */
+  public static class EntitySerializerPropertiesBuilder {
+    private final EntitySerializerProperties properties = new EntitySerializerProperties();
+
+    /**
+     * 
+     * @param includeMetadata
+     * @return EntitySerializerPropertiesBuilder
+     */
+    public EntitySerializerPropertiesBuilder
+      includeMetadata(final boolean includeMetadata) {
+    properties.includeMetadata = includeMetadata;
+    return this;
+   }
+
+   
+
+    /**
+     * @param serviceRoot
+     */
+    public final EntitySerializerPropertiesBuilder serviceRoot(final URI serviceRoot) {
+      properties.serviceRoot = serviceRoot;
+      return this;
+    }
+    
+    /**
+     * @param setting if payload has auto generated keys
+     */
+    public final EntitySerializerPropertiesBuilder isKeyAutoGenerated
+    (boolean isKeyAutoGenerated) {
+      properties.isKeyAutoGenerated = isKeyAutoGenerated;
+      return this;
+    }
+
+    /**
+     * Build properties object.
+     * @return assembled properties object
+     */
+    public final EntitySerializerProperties build() {
+      return properties;
+    }
+
+    /**
+     * 
+     * @param validatingFacets
+     * @return EntitySerializerPropertiesBuilder
+     */
+    public EntitySerializerPropertiesBuilder validatingFacets(final boolean validatingFacets) {
+      properties.validatingFacets = validatingFacets;
+      return this;
+    }
+
+    /**
+     * 
+     * @param properties
+     * @return EntitySerializerPropertiesBuilder
+     */
+    public EntitySerializerPropertiesBuilder fromProperties
+    (final EntitySerializerProperties properties) {
+      this.properties.validatingFacets = properties.validatingFacets;
+      this.properties.includeMetadata = properties.includeMetadata;
+      this.properties.isKeyAutoGenerated = properties.isKeyAutoGenerated;
+      return this;
+    }
+
+  }
+
+  /**
+   * 
+   * @param properties
+   * @return EntitySerializerPropertiesBuilder
+   */
+  public static EntitySerializerPropertiesBuilder fromProperties
+  (final EntitySerializerProperties properties) {
+    final EntitySerializerPropertiesBuilder builder =
+        EntitySerializerProperties.serviceRoot(properties.getServiceRoot());
+    return builder.fromProperties(properties);
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/ep/EntityStream.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/ep/EntityStream.java b/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/ep/EntityStream.java
new file mode 100644
index 0000000..21cc6d9
--- /dev/null
+++ b/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/ep/EntityStream.java
@@ -0,0 +1,55 @@
+/*
+ * 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.client.api.ep;
+
+import java.io.InputStream;
+
+/**
+ * Data representation for a single entity.
+ */
+public class EntityStream {
+
+  private InputStream content ;
+  private DeserializerProperties readProperties;
+  public InputStream getContent() {
+    return content;
+  }
+  /**
+   * Set the content
+   * @param content
+   */
+  public void setContent(InputStream content) {
+    this.content = content;
+  }
+  /**
+   * Get Read properties
+   * @return DeserializerProperties
+   */
+  public DeserializerProperties getReadProperties() {
+    return readProperties;
+  }
+  /**
+   * Set read properties
+   * @param readProperties
+   */
+  public void setReadProperties(DeserializerProperties readProperties) {
+    this.readProperties = readProperties;
+  }
+ 
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/ep/callback/OnDeserializeInlineContent.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/ep/callback/OnDeserializeInlineContent.java b/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/ep/callback/OnDeserializeInlineContent.java
new file mode 100644
index 0000000..0696848
--- /dev/null
+++ b/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/ep/callback/OnDeserializeInlineContent.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * 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.client.api.ep.callback;
+
+import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
+import org.apache.olingo.odata2.api.exception.ODataApplicationException;
+import org.apache.olingo.odata2.client.api.ep.DeserializerProperties;
+
+/**
+ * <p>
+ * Callback interface for the deep insert read calls (read of <code><m:inline></code> content).
+ * Typically the {@link #receiveReadProperties(EntityProviderReadProperties, EdmNavigationProperty)} method is called
+ * when an inline navigation property is found and will be read.
+ * </p>
+ *  
+ */
+public interface OnDeserializeInlineContent {
+
+  /**
+   * Receive (request) to be used {@link EntityProviderReadProperties} to read the found inline navigation property
+   * (<code>><m:inline>...</m:inline></code>).
+   * 
+   * @param readProperties read properties which are used to read enclosing parent entity
+   * @param navigationProperty emd navigation property information of found inline navigation property
+   * @return read properties which are used to read (de-serialize) found inline navigation property
+   * @throws ODataApplicationException
+   */
+  DeserializerProperties receiveReadProperties(DeserializerProperties readProperties,
+      EdmNavigationProperty navigationProperty) throws ODataApplicationException;
+
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/uri/EdmURIBuilder.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/uri/EdmURIBuilder.java b/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/uri/EdmURIBuilder.java
new file mode 100644
index 0000000..22278bd
--- /dev/null
+++ b/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/uri/EdmURIBuilder.java
@@ -0,0 +1,184 @@
+package org.apache.olingo.odata2.client.api.uri;
+
+import java.net.URI;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmFunctionImport;
+import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
+import org.apache.olingo.odata2.api.edm.EdmParameter;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+
+/**
+ * 
+ * This is an Edm Uri Builder
+ *
+ */
+public interface EdmURIBuilder {
+  /**
+   * Appends EntitySet segment to the URI.
+   *
+   * @param entitySet Edm entity set.
+   * @return current EdmURIBuilder instance
+   */
+  EdmURIBuilder appendEntitySetSegment(EdmEntitySet entitySet);
+  
+  /**
+   * Appends navigation segment to the URI.
+   *
+   * @param property navigation property.
+   * @return current EdmURIBuilder instance
+   */
+  EdmURIBuilder appendNavigationSegment(EdmNavigationProperty property);
+  
+  /**
+   * Appends key segment to the URI.
+   *
+   * @param property edm property
+   * @param value key value
+   * @return current EdmURIBuilder instance
+   */
+  EdmURIBuilder appendKeySegment(EdmProperty property, Object value);
+  
+  /**
+   * Appends key segment to the URI, for multiple keys.
+   *
+   * @param segmentValues segment values.
+   * @return current EdmURIBuilder instance
+   */
+  EdmURIBuilder appendKeySegment(Map<EdmProperty, Object> segmentValues);
+  
+  /**
+   * Appends property segment to the URI.
+   *
+   * @param property edmProperty
+   * @param segmentValue segment value.
+   * @return current EdmURIBuilder instance
+   */
+  EdmURIBuilder appendPropertySegment(EdmProperty property, String segmentValue);
+  
+  /**
+   * Adds expand query option.
+   *
+   * @param expandItems items to be expanded in-line
+   * @return current EdmURIBuilder instance
+   * @see QueryOption#EXPAND
+   */
+  EdmURIBuilder expand(String... expandItems);
+  
+  /**
+   * Adds select query option.
+   *
+   * @param selectItems select items
+   * @return current EdmURIBuilder instance
+   * @see QueryOption#SELECT
+   */
+  EdmURIBuilder select(String... selectItems);
+  
+  /**
+   * Adds orderby query option.
+   *
+   * @param property property string.
+   * @return current EdmURIBuilder instance
+   * @see QueryOption#ORDERBY
+   */
+  EdmURIBuilder orderBy(String property);
+  
+  /**
+   * Appends count segment to the URI.
+   * @return current EdmURIBuilder instance
+   */
+  EdmURIBuilder appendCountSegment();
+  
+  /**
+   * Appends metadata segment to the URI.
+   *
+   * @return current EdmURIBuilder instance
+   */
+  EdmURIBuilder appendMetadataSegment();
+  
+  /**
+   * Adds format query option.
+   *
+   * @param format media type acceptable in a response.
+   * @return current EdmURIBuilder instance
+   * @see QueryOption#FORMAT
+   */
+  EdmURIBuilder format(String format);
+  
+  /**
+   * Appends value segment to the URI.
+   *
+   * @return current EdmURIBuilder instance
+   */
+  EdmURIBuilder appendValueSegment();
+  
+  /**
+   * Adds the specified query option to the URI.
+   * <br />
+   * Concatenates value if the specified query option already exists.
+   *
+   * @param option query option.
+   * @param value query option value.
+   * @return current EdmURIBuilder instance
+   */
+  EdmURIBuilder addQueryOption(QueryOption option, String value);
+  
+  /**
+   * Adds filter query option.
+   *
+   * @param filter filter string.
+   * @return current EdmURIBuilder instance
+   * @see QueryOption#FILTER
+   */
+  EdmURIBuilder filter(String filter);
+
+  /**
+   * Adds top query option.
+   *
+   * @param top maximum number of entities to be returned.
+   * @return current EdmURIBuilder instance
+   * @see QueryOption#TOP
+   */
+  EdmURIBuilder top(int top);
+
+  /**
+   * Adds skip query option.
+   *
+   * @param skip number of entities to be skipped into the response.
+   * @return current EdmURIBuilder instance
+   * @see QueryOption#SKIP
+   */
+  EdmURIBuilder skip(int skip);
+  
+  /**
+   * Adds custom query option
+   * @param paramName parameter name
+   * @param paramValue parameter value
+   * @return current EdmURIBuilder instance
+   */
+  EdmURIBuilder addCustomQueryOption(String paramName, Object paramValue);
+  
+  /**
+   * Appends Function import to the uri
+   * @param functionImport
+   * @return current EdmURIBuilder instance
+   */
+  EdmURIBuilder appendFunctionImportSegment(EdmFunctionImport functionImport);
+  
+  /**
+   * Appends function import parameters
+   * @param functionImportParams
+   * @return current EdmURIBuilder instance
+   */
+  EdmURIBuilder appendFunctionImportParameters(Map<EdmParameter, Object> functionImportParams);
+  
+  /**
+   * Build OData URI.
+   *
+   * @return OData URI.
+   */
+  URI build();
+  
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/uri/QueryOption.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/uri/QueryOption.java b/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/uri/QueryOption.java
new file mode 100644
index 0000000..36b4bf9
--- /dev/null
+++ b/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/uri/QueryOption.java
@@ -0,0 +1,70 @@
+package org.apache.olingo.odata2.client.api.uri;
+
+/**
+ * This is a list of query options
+ *
+ */
+public enum QueryOption {
+
+  /**
+   * The $count system query option allows clients to request a count of the matching resources included with the
+   * resources in the response. The $count query option has a Boolean value of true or false.
+   */
+  COUNT("$count"),
+  /**
+   * This option indicates entities associated with the EntityType instance or EntitySet, identified by the resource
+   * path section of the URI, and MUST be represented inline in the data service's response.
+   */
+  EXPAND("$expand"),
+  /**
+   * This option specifies the media type acceptable in a response. If present, this value SHOULD take precedence over
+   * value(s) specified in an Accept request header.
+   */
+  FORMAT("$format"),
+  /**
+   * This option is used to specify that a subset of the properties of the entities identified by the path of the
+   * request URI and $expand query option SHOULD be returned in the response from the data service.
+   */
+  SELECT("$select"),
+  /**
+   * This option specifies the sort properties and sort direction (ascending or descending) that the data service MUST
+   * use to order the entities in the EntitySet, identified by the resource path section of the URI.
+   */
+  ORDERBY("$orderby"),
+  /**
+   * This option specifies a positive integer N that is the maximum number of entities in the EntitySet, identified by
+   * the resource path section of the URI, that the data service MUST return.
+   */
+  TOP("$top"),
+  /**
+   * This option specifies a positive integer N that represents the number of entities, counted from the first entity in
+   * the EntitySet and ordered as specified by the $orderby option, that the data service should skip when returning the
+   * entities in the EntitySet, which is identified by the resource path section of the URI. The data service SHOULD
+   * return all subsequent entities, starting from the one in position N+1.
+   */
+  SKIP("$skip"),
+  /**
+   * The value of a $skiptoken query option is an opaque token which identifies an index into the collection
+   * of entities identified by the URI containing the $skiptoken parameter.
+   */
+  SKIPTOKEN("$skiptoken"),
+  /**
+   * This option specifies a predicate used to filter the elements from the EntitySet identified by the resource path
+   * section of the URI.
+   */
+  FILTER("$filter");
+  
+  private final String value;
+  
+  private QueryOption() {
+    this.value = "";
+  } 
+  
+  private QueryOption(final String value) {
+    this.value = value;
+  }
+  
+  public String getValue() {
+    return value;
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/uri/SegmentType.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/uri/SegmentType.java b/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/uri/SegmentType.java
new file mode 100644
index 0000000..1d50e08
--- /dev/null
+++ b/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/uri/SegmentType.java
@@ -0,0 +1,76 @@
+package org.apache.olingo.odata2.client.api.uri;
+
+/**
+ * URI Segment types.
+ */
+public enum SegmentType {
+
+  /**
+   * Initial will be the builder state to begin with a service root url
+   */
+  INITIAL,
+  /**
+   * When we append entity set state is changed to ENTITYSET
+   */
+  ENTITYSET,
+  /**
+   * 
+   */
+  ENTITY,
+  /**
+   * When we append simple property state is changed to SIMPLEPROPERTY
+   */
+  SIMPLEPROPERTY,
+  /**
+   * When there is a key in segment
+   */
+  KEY,
+  /**
+   * When we append simple complex state is changed to COMPLEXPROPERTY
+   */
+  COMPLEXPROPERTY,
+  /**
+   * When there is navigation to many then the state is NAVIGATION_TO_MANY
+   */
+  NAVIGATION_TO_MANY,
+  /**
+   * When there is navigation to many with a key then the state is
+   * NAVIGATION_TO_MANY_WITH_KEY
+   */
+  NAVIGATION_TO_MANY_WITH_KEY,
+  /**
+   * When there is navigation to one then the state is NAVIGATION_TO_ONE
+   */
+  NAVIGATION_TO_ONE,
+  /**
+   * When there is count query option
+   */
+  COUNT("$count"),
+  /**
+   * When there is a value query option
+   */
+  VALUE("$value"),
+  /**
+   * When there is a metadata uri segment
+   */
+  METADATA("$metadata"),
+  PROPERTY,
+  NAVIGATION,
+  FUNCTIONIMPORT,
+  FUNCTIONIMPORT_WITH_KEY,
+  FUNCTIONIMPORT_MANY;
+
+  private final String value;
+
+  private SegmentType() {
+    this.value = "";
+  }
+
+  private SegmentType(final String value) {
+    this.value = value;
+  }
+
+  public String getValue() {
+    return value;
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/uri/URIBuilder.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/uri/URIBuilder.java b/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/uri/URIBuilder.java
new file mode 100644
index 0000000..7ecd908
--- /dev/null
+++ b/odata2-lib/odata-client-api/src/main/java/org/apache/olingo/odata2/client/api/uri/URIBuilder.java
@@ -0,0 +1,174 @@
+package org.apache.olingo.odata2.client.api.uri;
+
+import java.net.URI;
+import java.util.Map;
+
+/**
+ * This is a URIBuilder class
+ *
+ */
+public interface URIBuilder {
+  
+  /**
+   * Appends EntitySet segment to the URI.
+   *
+   * @param entitySet String entity set.
+   * @return current URIBuilder instance
+   */
+  URIBuilder appendEntitySetSegment(String entitySet);
+  
+  /**
+   * Appends navigation segment to the URI.
+   *
+   * @param navigationProperty String navigation property.
+   * @return current URIBuilder instance
+   */
+  URIBuilder appendNavigationSegment(String navigationProperty);
+
+  /**
+   * Appends key segment to the URI.
+   *
+   * @param val segment value.
+   * @return current URIBuilder instance
+   */
+  URIBuilder appendKeySegment(Object val);
+  
+  /**
+   * Appends key segment to the URI, for multiple keys.
+   *
+   * @param segmentValues segment values.
+   * @return current URIBuilder instance
+   */
+  URIBuilder appendKeySegment(Map<String, Object> segmentValues);
+  
+  /**
+   * Appends property segment to the URI.
+   *
+   * @param segmentValue String segment value.
+   * @return current URIBuilder instance
+   */
+  URIBuilder appendPropertySegment(String segmentValue);
+  
+  /**
+   * Adds expand query option.
+   *
+   * @param expandItems items to be expanded in-line
+   * @return current URIBuilder instance
+   * @see QueryOption#EXPAND
+   */
+  URIBuilder expand(String... expandItems);
+  
+  /**
+   * Adds select query option.
+   *
+   * @param selectItems select items
+   * @return current URIBuilder instance
+   * @see QueryOption#SELECT
+   */
+  URIBuilder select(String... selectItems);
+  
+  /**
+   * Adds orderby query option.
+   *
+   * @param order order string.
+   * @return current URIBuilder instance
+   * @see QueryOption#ORDERBY
+   */
+  URIBuilder orderBy(String order);
+  
+  /**
+   * Appends count segment to the URI.
+   * @return current URIBuilder instance
+   */
+  URIBuilder appendCountSegment();
+  
+  /**
+   * Appends metadata segment to the URI.
+   *
+   * @return current URIBuilder instance
+   */
+  URIBuilder appendMetadataSegment();
+  
+  /**
+   * Adds format query option.
+   *
+   * @param format media type acceptable in a response.
+   * @return current URIBuilder instance
+   * @see QueryOption#FORMAT
+   */
+  URIBuilder format(String format);
+  
+  /**
+   * Appends value segment to the URI.
+   *
+   * @return current URIBuilder instance
+   */
+  URIBuilder appendValueSegment();
+  
+  /**
+   * Adds the specified query option to the URI.
+   * <br />
+   * Concatenates value if the specified query option already exists.
+   *
+   * @param option query option.
+   * @param value query option value.
+   * @return current URIBuilder instance
+   */
+  URIBuilder addQueryOption(QueryOption option, String value);
+  
+  /**
+   * Adds filter query option.
+   *
+   * @param filter filter string.
+   * @return current URIBuilder instance
+   * @see QueryOption#FILTER
+   */
+  URIBuilder filter(String filter);
+
+  /**
+   * Adds top query option.
+   *
+   * @param top maximum number of entities to be returned.
+   * @return current URIBuilder instance
+   * @see QueryOption#TOP
+   */
+  URIBuilder top(int top);
+
+  /**
+   * Adds skip query option.
+   *
+   * @param skip number of entities to be skipped into the response.
+   * @return current URIBuilder instance
+   * @see QueryOption#SKIP
+   */
+  URIBuilder skip(int skip);
+  
+  /**
+   * Adds custom query option
+   * @param paramName parameter name 
+   * @param paramValue parameter value
+   * @return current URIBuilder instance
+   */
+  URIBuilder addCustomQueryOption(String paramName, Object paramValue);
+  
+  /**
+   * Appends function import to the uri
+   * @param functionImport
+   * @return current URIBuilder instance
+   */
+  URIBuilder appendFunctionImportSegment(String functionImport);
+  
+  /**
+   * Appends function import parameters to the uri
+   * @param functionImportParams
+   * @return current URIBuilder instance
+   */
+  URIBuilder appendFunctionImportParameters(Map<String, Object> functionImportParams);
+  
+  /**
+   * Build OData URI.
+   *
+   * @return OData URI.
+   */
+  URI build();
+}


[08/24] olingo-odata2 git commit: [OLINGO-1253]Client Module for Olingo v2

Posted by ar...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/serializer/JsonEntryEntitySerializerTest.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/serializer/JsonEntryEntitySerializerTest.java b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/serializer/JsonEntryEntitySerializerTest.java
new file mode 100644
index 0000000..f7e0433
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/serializer/JsonEntryEntitySerializerTest.java
@@ -0,0 +1,1027 @@
+/*******************************************************************************
+ * 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.client.core.ep.serializer;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.TimeZone;
+
+import javax.xml.stream.XMLStreamException;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmConcurrencyMode;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmEntityType;
+import org.apache.olingo.odata2.api.edm.EdmFacets;
+import org.apache.olingo.odata2.api.edm.EdmMapping;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeException;
+import org.apache.olingo.odata2.api.edm.EdmTyped;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.processor.ODataResponse;
+import org.apache.olingo.odata2.client.api.edm.ClientEdm;
+import org.apache.olingo.odata2.client.api.edm.EdmDataServices;
+import org.apache.olingo.odata2.client.api.ep.Entity;
+import org.apache.olingo.odata2.client.api.ep.EntityCollection;
+import org.apache.olingo.odata2.client.api.ep.EntitySerializerProperties;
+import org.apache.olingo.odata2.client.core.ep.JsonSerializerDeserializer;
+import org.apache.olingo.odata2.client.core.ep.deserializer.XmlMetadataDeserializer;
+import org.apache.olingo.odata2.core.ep.EntityProviderProducerException;
+import org.apache.olingo.odata2.testutil.fit.BaseTest;
+import org.apache.olingo.odata2.testutil.helper.StringHelper;
+import org.apache.olingo.odata2.testutil.mock.MockFacade;
+import org.junit.Test;
+
+import com.google.gson.Gson;
+import com.google.gson.internal.LinkedTreeMap;
+
+/**
+ *  
+ */
+public class JsonEntryEntitySerializerTest extends BaseTest { 
+  protected static final String BASE_URI = "http://host:80/service/";
+  protected static final EntitySerializerProperties DEFAULT_PROPERTIES =
+      EntitySerializerProperties.serviceRoot(URI.create(BASE_URI)).build();
+  protected static final String ERROR_MSG = "Entity or expanded entity cannot have null value.";
+  protected static final String ERROR_MSG1 = "Navigation has to be either an Entity or a Map.";
+  
+
+  @Test
+  public void entry() throws Exception {
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+    Entity entity = new Entity();
+    entity.addProperty("Id", "1");
+    entity.addProperty("isScrumTeam", true);
+    entity.setWriteProperties(DEFAULT_PROPERTIES);
+
+    final ODataResponse response = new JsonSerializerDeserializer().writeEntry(entitySet, entity);
+    final String json = verifyResponse(response);
+    assertEquals("{\"Id\":\"1\",\"isScrumTeam\":true}", json);
+  }
+
+  @Test
+  public void entryWithoutKey() throws Exception {
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+    Entity entity = new Entity();
+    entity.addProperty("isScrumTeam", true);
+    entity.setWriteProperties(DEFAULT_PROPERTIES);
+
+    final ODataResponse response = new JsonSerializerDeserializer().writeEntry(entitySet, entity);
+    final String json = StringHelper.inputStreamToString((InputStream) response.getEntity());
+    assertNotNull(json);
+    assertEquals("{\"isScrumTeam\":true}", json);
+  }
+  
+  @SuppressWarnings("unchecked")
+  @Test
+  public void includeMetadata() throws Exception {
+    Calendar date = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
+    date.clear();
+    date.set(1999, 0, 1);
+    Entity entity = new Entity();
+    entity.addProperty("EmployeeId", "1");
+    entity.addProperty("ImmageUrl", null);
+    entity.addProperty("ManagerId", "1");
+    entity.addProperty("Age", new Integer(52));
+    entity.addProperty("RoomId", "1");
+    entity.addProperty("EntryDate", date);
+    entity.addProperty("TeamId", "42");
+    entity.addProperty("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");
+    entity.addProperty("Location", locationData);
+    
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+    EntitySerializerProperties properties =
+        EntitySerializerProperties.fromProperties(DEFAULT_PROPERTIES).includeMetadata(true).build();
+    entity.setWriteProperties(properties);
+    final ODataResponse response = new JsonSerializerDeserializer().writeEntry(entitySet, entity);
+    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"));
+  }
+
+  @Test
+  public void includeMetadataWithoutKey() throws Exception {
+    Entity employeeData = new Entity();
+    employeeData.addProperty("ManagerId", "1");
+    employeeData.addProperty("Age", new Integer(52));
+    employeeData.addProperty("RoomId", "1");
+    employeeData.addProperty("TeamId", "42");
+
+    List<String> selectedProperties = new ArrayList<String>();
+    selectedProperties.add("ManagerId");
+    selectedProperties.add("Age");
+    selectedProperties.add("RoomId");
+    selectedProperties.add("TeamId");
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+
+    EntitySerializerProperties properties =
+        EntitySerializerProperties.fromProperties(DEFAULT_PROPERTIES).includeMetadata(true)
+            .build();
+    employeeData.setWriteProperties(properties);
+    try {
+      new JsonSerializerDeserializer().writeEntry(entitySet, employeeData);
+    } catch (EntityProviderException e) {
+      assertEquals("The metadata do not allow a null value for property 'EmployeeId'.", e.getMessage());
+    }
+  }
+
+  @SuppressWarnings("unchecked")
+  @Test
+  public void testNavigationLink() throws Exception {
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+    Entity employeeData = new Entity();
+    employeeData.addProperty("EmployeeId", "1");
+
+    Map<String, Object> managerLink = new HashMap<String, Object>();
+    managerLink.put("EmployeeId", "1");
+    employeeData.addNavigation("ne_Manager", managerLink);
+
+    EntitySerializerProperties properties =
+        EntitySerializerProperties.fromProperties(DEFAULT_PROPERTIES).build();
+    employeeData.setWriteProperties(properties);
+    final ODataResponse response = new JsonSerializerDeserializer().writeEntry(entitySet, employeeData);
+    Map<String, Object> employee =
+        (Map<String, Object>) new Gson().fromJson(new InputStreamReader((InputStream) response.getEntity()), Map.class);
+    assertNull(employee.get("__metadata"));
+    assertNull(employee.get("ne_Team"));
+    assertNull(employee.get("ne_Room"));
+
+    assertEquals("1", employee.get("EmployeeId"));
+    Map<String, Object> map = (Map<String, Object>) employee.get("ne_Manager");
+    map = (Map<String, Object>) map.get("__deferred");
+    assertEquals("http://host:80/service/Managers('1')", map.get("uri"));
+  }
+
+  @SuppressWarnings("unchecked")
+  @Test
+  public void addEntityToNavigation() throws Exception {
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+    Entity employeeData = new Entity();
+    employeeData.addProperty("EmployeeId", "1");
+
+    Entity managerLink = new Entity();
+    managerLink.addProperty("EmployeeId", "1");
+    employeeData.addNavigation("ne_Manager", managerLink);
+
+    EntitySerializerProperties properties =
+        EntitySerializerProperties.fromProperties(DEFAULT_PROPERTIES).build();
+    employeeData.setWriteProperties(properties);
+    final ODataResponse response = new JsonSerializerDeserializer().writeEntry(entitySet, employeeData);
+    Map<String, Object> employee =
+        (Map<String, Object>) new Gson().fromJson(new InputStreamReader((InputStream) response.getEntity()), Map.class);
+    assertNull(employee.get("__metadata"));
+    assertNull(employee.get("ne_Team"));
+    assertNull(employee.get("ne_Room"));
+
+    assertEquals("1", employee.get("EmployeeId"));
+    Map<String, Object> map = (Map<String, Object>) employee.get("ne_Manager");
+    assertEquals(map.get("EmployeeId"), "1");
+  }
+  
+  @SuppressWarnings("unchecked")
+  @Test
+  public void addEntityAndMapToNavigation() throws Exception {
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+    Entity employeeData = new Entity();
+    employeeData.addProperty("EmployeeId", "1");
+
+    Entity managerLink = new Entity();
+    managerLink.addProperty("EmployeeId", "1");
+    employeeData.addNavigation("ne_Manager", managerLink);
+    
+    Map<String, Object> navigationLink = new HashMap<String, Object>();
+    navigationLink.put("Id", "1");
+    employeeData.addNavigation("ne_Room", navigationLink);
+
+    EntitySerializerProperties properties =
+        EntitySerializerProperties.fromProperties(DEFAULT_PROPERTIES).build();
+    employeeData.setWriteProperties(properties);
+    final ODataResponse response = new JsonSerializerDeserializer().writeEntry(entitySet, employeeData);
+    Map<String, Object> employee =
+        (Map<String, Object>) new Gson().fromJson(new InputStreamReader((InputStream) response.getEntity()), Map.class);
+    assertNull(employee.get("__metadata"));
+    assertNull(employee.get("ne_Team"));
+    assertNotNull(employee.get("ne_Room"));
+
+    assertEquals("1", employee.get("EmployeeId"));
+    Map<String, Object> map = (Map<String, Object>) employee.get("ne_Manager");
+    assertEquals(map.get("EmployeeId"), "1");
+    
+    Map<String, Object> roomMap = (Map<String, Object>) employee.get("ne_Room");
+    assertEquals(((Map<String, Object>)roomMap.get("__deferred")).get("uri"), 
+        "http://host:80/service/Rooms('1')");
+  }
+  
+  @Test
+  public void addNullToNavigation() throws Exception {
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+    Entity employeeData = new Entity();
+    employeeData.addProperty("EmployeeId", "1");
+    employeeData.addNavigation("ne_Manager", null); 
+
+    EntitySerializerProperties properties =
+        EntitySerializerProperties.fromProperties(DEFAULT_PROPERTIES).build();
+    employeeData.setWriteProperties(properties);
+    try {
+      new JsonSerializerDeserializer().writeEntry(entitySet, employeeData);
+    } catch (EntityProviderException e) {
+      assertEquals(ERROR_MSG, e.getMessage());
+    }
+  }
+  
+  @Test
+  public void addEmptyEntityToNavigation() throws Exception {
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+    Entity employeeData = new Entity();
+    employeeData.addProperty("EmployeeId", "1");
+    Entity managerLink = new Entity();
+    employeeData.addNavigation("ne_Manager", managerLink); 
+
+    EntitySerializerProperties properties =
+        EntitySerializerProperties.fromProperties(DEFAULT_PROPERTIES).build();
+    employeeData.setWriteProperties(properties);
+    final ODataResponse response = new JsonSerializerDeserializer().writeEntry(entitySet, employeeData);
+    @SuppressWarnings("unchecked")
+    Map<String, Object> employee =
+        (Map<String, Object>) new Gson().fromJson(new InputStreamReader((InputStream) response.getEntity()), Map.class);
+    assertNull(employee.get("__metadata"));
+    assertNull(employee.get("ne_Team"));
+    assertNull(employee.get("ne_Room"));
+
+    assertEquals("1", employee.get("EmployeeId"));
+    assertNotNull(employee.get("ne_Manager"));
+  }
+  
+  @Test
+  public void addEmptyMapToNavigation() throws Exception {
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+    Entity employeeData = new Entity();
+    employeeData.addProperty("EmployeeId", "1");
+    Map<String, Object> managerLink = new HashMap<String, Object>();
+    employeeData.addNavigation("ne_Manager", managerLink); 
+
+    EntitySerializerProperties properties =
+        EntitySerializerProperties.fromProperties(DEFAULT_PROPERTIES).build();
+    employeeData.setWriteProperties(properties);
+    final ODataResponse response = new JsonSerializerDeserializer().writeEntry(entitySet, employeeData);
+    @SuppressWarnings("unchecked")
+    Map<String, Object> employee =
+        (Map<String, Object>) new Gson().fromJson(new InputStreamReader((InputStream) response.getEntity()), Map.class);
+    assertNull(employee.get("__metadata"));
+    assertNull(employee.get("ne_Team"));
+    assertNull(employee.get("ne_Room"));
+
+    assertEquals("1", employee.get("EmployeeId"));
+    assertNull(employee.get("ne_Manager"));
+  }
+  
+  @Test
+  public void addIncorrectTypeToNavigation() throws Exception {
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+    Entity employeeData = new Entity();
+    employeeData.addProperty("EmployeeId", "1");
+    List<String> managerLink = new ArrayList<String>();
+    employeeData.addNavigation("ne_Manager", managerLink); 
+
+    EntitySerializerProperties properties =
+        EntitySerializerProperties.fromProperties(DEFAULT_PROPERTIES).build();
+    employeeData.setWriteProperties(properties);
+    try {
+      new JsonSerializerDeserializer().writeEntry(entitySet, employeeData);
+    } catch (EntityProviderException e) {
+      assertEquals(ERROR_MSG1, e.getMessage());
+    }
+  }
+  
+  @Test(expected = EdmSimpleTypeException.class)
+  public void serializeWithFacetsValidation() throws Throwable {
+    Edm edm = MockFacade.getMockEdm();
+    EdmTyped roomNameProperty = edm.getEntityType("RefScenario", "Room").getProperty("Name");
+    EdmFacets facets = mock(EdmFacets.class);
+    when(facets.getMaxLength()).thenReturn(3);
+    when(((EdmProperty) roomNameProperty).getFacets()).thenReturn(facets);
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Rooms");
+
+    String name = "1234567";
+    Entity roomData = new Entity();
+    roomData.addProperty("Id", "4711");
+    roomData.addProperty("Name", name);
+    EntitySerializerProperties properties = EntitySerializerProperties
+        .fromProperties(DEFAULT_PROPERTIES).validatingFacets(true).build();
+    roomData.setWriteProperties(properties);
+    try {
+      final ODataResponse response = new JsonSerializerDeserializer().writeEntry(entitySet, roomData);
+      final String json = verifyResponse(response);
+      assertNotNull(response);
+      assertEquals("{\"Id\":\"1\",\"Name\":null,\"isScrumTeam\":true}", json);
+    } catch (EntityProviderException e) {
+      throw e.getCause();
+    }
+  }
+
+  @Test
+  public void serializeWithoutFacetsValidation() throws Exception {
+    Edm edm = MockFacade.getMockEdm();
+    EdmTyped roomNameProperty = edm.getEntityType("RefScenario", "Room").getProperty("Name");
+    EdmFacets facets = mock(EdmFacets.class);
+    when(facets.getMaxLength()).thenReturn(3);
+    when(((EdmProperty) roomNameProperty).getFacets()).thenReturn(facets);
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Rooms");
+
+    String name = "1234567890";
+    Entity roomData = new Entity();
+    roomData.addProperty("Id", "4711");
+    roomData.addProperty("Name", name);
+    EntitySerializerProperties properties = EntitySerializerProperties
+        .fromProperties(DEFAULT_PROPERTIES).validatingFacets(false).build();
+    roomData.setWriteProperties(properties);
+    final ODataResponse response = new JsonSerializerDeserializer().writeEntry(entitySet, roomData);
+    final String json = verifyResponse(response);
+    assertNotNull(response);
+    assertEquals("{\"Id\":\"4711\",\"Name\":\"1234567890\"}", json);
+  }
+
+  @Test
+  public void entryWithNullData() throws Exception {
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+    try {
+      new JsonSerializerDeserializer().writeEntry(entitySet, null);
+    } catch (EntityProviderException e) {
+      assertEquals(ERROR_MSG, e.getMessage());
+    }
+  }
+  
+  @Test
+  public void entryWithEmptyData() throws Exception {
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+    Entity entity = new Entity();
+    entity.setWriteProperties(DEFAULT_PROPERTIES);
+    final ODataResponse response = new JsonSerializerDeserializer().writeEntry(entitySet, entity);
+    final String json = verifyResponse(response);
+    assertNotNull(json);
+    assertEquals("{}", json);
+  }
+
+  @Test
+  public void mediaLinkEntry() throws Exception {
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getEntityContainer("Container2").getEntitySet("Photos");
+    Entity photoData = new Entity();
+    photoData.addProperty("Id", 1);
+    photoData.addProperty("Type", "image/png");
+    photoData.addProperty("BinaryData", new byte[] { -1, 0, 1, 2 });
+    photoData.addProperty("getType", "image/png");
+    photoData.setWriteProperties(DEFAULT_PROPERTIES);
+
+    final ODataResponse response = new JsonSerializerDeserializer().writeEntry(entitySet, photoData);
+    final String json = verifyResponse(response);
+    assertEquals("{\"Id\":1,\"Type\":\"image/png\",\"BinaryData\":\"/wABAg==\"}",
+        json);
+  }
+
+  @Test
+  public void entryWithExpandedEntryButNullData() throws Exception {
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+    Entity roomData = new Entity();
+    roomData.addProperty("Id", "1");
+    roomData.addProperty("Version", 1);
+    roomData.addNavigation("nr_Building", null);
+    roomData.setWriteProperties(EntitySerializerProperties.serviceRoot(URI.create(BASE_URI))
+                .build());
+    try {
+      new JsonSerializerDeserializer().writeEntry(entitySet, roomData);
+    } catch (EntityProviderException e) {
+      assertEquals(ERROR_MSG, e.getMessage());
+    }
+  }
+ 
+  @SuppressWarnings("unchecked")
+  @Test
+  public void entryWithExpandedEntryButEmptyData() throws Exception {
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+    Entity roomData = new Entity();
+    roomData.addProperty("Id", "1");
+    roomData.addProperty("Version", 1);
+    roomData.addNavigation("nr_Building", new Entity());
+    roomData.setWriteProperties(EntitySerializerProperties.serviceRoot(URI.create(BASE_URI))
+        .build());
+
+    ODataResponse response =
+        new JsonSerializerDeserializer().writeEntry(entitySet, roomData);
+    assertNotNull(response);
+    assertNotNull(response.getEntity());
+    assertNull("EntitypProvider must not set content header", response.getContentHeader());
+
+    Map<String, Object> roomEntry =
+        new Gson().fromJson(new InputStreamReader((InputStream) response.getEntity()), Map.class);
+    assertEquals(3, roomEntry.size());
+    assertTrue(roomEntry.containsKey("nr_Building"));
+    assertNotNull(roomEntry.get("nr_Building"));
+    assertTrue(((Map<String, Object>) roomEntry.get("nr_Building")).size() == 0);
+  }
+
+  @Test
+  public void entryWithExpandedEntry() throws Exception {
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+    Entity roomData = new Entity();
+    roomData.addProperty("Id", "1");
+    roomData.addProperty("Version", 1);
+    roomData.setWriteProperties(EntitySerializerProperties.serviceRoot(URI.create(BASE_URI))
+                .build());
+    
+    Entity buildingData = new Entity();
+    buildingData.addProperty("Id", "1");
+    buildingData.setWriteProperties(EntitySerializerProperties.serviceRoot(URI.create(BASE_URI)).build());
+    roomData.addNavigation("nr_Building", buildingData);
+
+    final ODataResponse response =
+        new JsonSerializerDeserializer().writeEntry(entitySet, roomData);
+    final String json = verifyResponse(response);
+    assertEquals("{\"Id\":\"1\",\"Version\":1,"
+        + "\"nr_Building\":{\"Id\":\"1\"}}",
+        json);
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void entryWithExpandedEntryWithFacets() throws Exception {
+    Edm edm = MockFacade.getMockEdm();
+    EdmTyped imageUrlProperty = edm.getEntityType("RefScenario", "Employee").getProperty("ImageUrl");
+    EdmFacets facets = mock(EdmFacets.class);
+    when(facets.getMaxLength()).thenReturn(1);
+    when(((EdmProperty) imageUrlProperty).getFacets()).thenReturn(facets);
+
+    Entity roomData = new Entity();
+    roomData.addProperty("Id", "1");
+    roomData.addProperty("Name", "Neu Schwanstein");
+    roomData.addProperty("Seats", new Integer(20));
+    roomData.addProperty("Version", new Integer(3));
+    
+    Entity employeeData = new Entity();
+    employeeData.addProperty("EmployeeId", "1");
+    employeeData.addProperty("ImageUrl", "hhtp://url");
+    employeeData.setWriteProperties(EntitySerializerProperties.serviceRoot(URI.create(BASE_URI))
+        .validatingFacets(true).build());
+    roomData.addNavigation("nr_Employees", employeeData);
+    roomData.setWriteProperties(EntitySerializerProperties.serviceRoot(URI.create(BASE_URI))
+                .build());
+
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Rooms");
+    final ODataResponse response =
+        new JsonSerializerDeserializer().writeEntry(entitySet, roomData);
+    assertNotNull(response);
+  }
+
+  @Test
+  public void entryWithExpandedEntryIgnoreFacets() throws Exception {
+    Edm edm = MockFacade.getMockEdm();
+    EdmTyped imageUrlProperty = edm.getEntityType("RefScenario", "Employee").getProperty("ImageUrl");
+    EdmFacets facets = mock(EdmFacets.class);
+    when(facets.getMaxLength()).thenReturn(1);
+    when(((EdmProperty) imageUrlProperty).getFacets()).thenReturn(facets);
+
+    Entity roomData = new Entity();
+    roomData.addProperty("Id", "1");
+    roomData.addProperty("Name", "Neu Schwanstein");
+    roomData.addProperty("Seats", new Integer(20));
+    roomData.addProperty("Version", new Integer(3));
+    roomData.setWriteProperties(DEFAULT_PROPERTIES);
+    
+    EntityCollection employeeCollection = new EntityCollection();
+    Entity employeeData = new Entity();
+    employeeData.addProperty("EmployeeId", "1");
+    employeeData.addProperty("ImageUrl", "hhtp://url");
+    employeeData.setWriteProperties(EntitySerializerProperties.serviceRoot(URI.create(BASE_URI))
+        .validatingFacets(false).build());
+    employeeCollection.addEntity(employeeData);
+    roomData.addNavigation("nr_Employees", employeeCollection);
+
+    EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Rooms");
+    final ODataResponse response =
+        new JsonSerializerDeserializer().writeEntry(entitySet, roomData);
+    final String json = verifyResponse(response);
+    assertEquals("{\"Id\":\"1\",\"Name\":\"Neu Schwanstein\",\"Seats\":20,\"Version\":3,"
+        + "\"nr_Employees\":[{\"EmployeeId\":\"1\",\"ImageUrl\":\"hhtp://url\"}]}",
+        json);
+  }
+
+  @SuppressWarnings("unchecked")
+  @Test
+  public void serializeWithCustomSrcAttributeOnEmployee() throws Exception {
+    Entity employeeData = new Entity();
+
+    Calendar date = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
+    date.clear();
+    date.set(1999, 0, 1);
+
+    employeeData.addProperty("EmployeeId", "1");
+    employeeData.addProperty("ImmageUrl", null);
+    employeeData.addProperty("ManagerId", "1");
+    employeeData.addProperty("Age", new Integer(52));
+    employeeData.addProperty("RoomId", "1");
+    employeeData.addProperty("EntryDate", date);
+    employeeData.addProperty("TeamId", "42");
+    employeeData.addProperty("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.addProperty("Location", locationData);
+
+    String mediaResourceSourceKey = "~src";
+    employeeData.addProperty(mediaResourceSourceKey, "http://localhost:8080/images/image1");
+    employeeData.setWriteProperties(EntitySerializerProperties.serviceRoot(URI.create(BASE_URI)).
+        includeMetadata(true).build());
+
+    EdmEntitySet employeesSet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+    EdmMapping mapping = employeesSet.getEntityType().getMapping();
+    when(mapping.getMediaResourceSourceKey()).thenReturn(mediaResourceSourceKey);
+
+    ODataResponse response = new JsonSerializerDeserializer().writeEntry(employeesSet, employeeData);
+    String jsonString = verifyResponse(response);
+    Gson gson = new Gson();
+    LinkedTreeMap<String, Object> jsonMap = gson.fromJson(jsonString, LinkedTreeMap.class);
+    jsonMap = (LinkedTreeMap<String, Object>) jsonMap.get("__metadata");
+
+    assertEquals("http://localhost:8080/images/image1", jsonMap.get("media_src"));
+    assertEquals("application/octet-stream", jsonMap.get("content_type"));
+    assertEquals("http://host:80/service/Employees('1')/$value", jsonMap.get("edit_media"));
+  }
+
+  @SuppressWarnings("unchecked")
+  @Test
+  public void serializeWithCustomSrcAndTypeAttributeOnEmployee() throws Exception {
+    Entity employeeData = new Entity();
+
+    Calendar date = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
+    date.clear();
+    date.set(1999, 0, 1);
+
+    employeeData.addProperty("EmployeeId", "1");
+    employeeData.addProperty("ImmageUrl", null);
+    employeeData.addProperty("ManagerId", "1");
+    employeeData.addProperty("Age", new Integer(52));
+    employeeData.addProperty("RoomId", "1");
+    employeeData.addProperty("EntryDate", date);
+    employeeData.addProperty("TeamId", "42");
+    employeeData.addProperty("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.addProperty("Location", locationData);
+    String mediaResourceSourceKey = "~src";
+    employeeData.addProperty(mediaResourceSourceKey, "http://localhost:8080/images/image1");
+    String mediaResourceMimeTypeKey = "~type";
+    employeeData.addProperty(mediaResourceMimeTypeKey, "image/jpeg");
+    employeeData.setWriteProperties(EntitySerializerProperties.serviceRoot(URI.create(BASE_URI)).
+        includeMetadata(true).build());
+
+    EdmEntitySet employeesSet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+    EdmMapping mapping = employeesSet.getEntityType().getMapping();
+    when(mapping.getMediaResourceSourceKey()).thenReturn(mediaResourceSourceKey);
+    when(mapping.getMediaResourceMimeTypeKey()).thenReturn(mediaResourceMimeTypeKey);
+
+    ODataResponse response = new JsonSerializerDeserializer().writeEntry(employeesSet, employeeData);
+    String jsonString = verifyResponse(response);
+
+    Gson gson = new Gson();
+    LinkedTreeMap<String, Object> jsonMap = gson.fromJson(jsonString, LinkedTreeMap.class);
+    jsonMap = (LinkedTreeMap<String, Object>) jsonMap.get("__metadata");
+
+    assertEquals("http://localhost:8080/images/image1", jsonMap.get("media_src"));
+    assertEquals("image/jpeg", jsonMap.get("content_type"));
+    assertEquals("http://host:80/service/Employees('1')/$value", jsonMap.get("edit_media"));
+  }
+  
+  @SuppressWarnings("unchecked")
+  @Test
+  public void serializeWithCustomSrcAttributeOnRoom() throws Exception {
+    Entity roomData = new Entity();
+    roomData.addProperty("Id", "1");
+    roomData.addProperty("Name", "Neu Schwanstein");
+    roomData.addProperty("Seats", new Integer(20));
+    roomData.addProperty("Version", new Integer(3));
+
+    String mediaResourceSourceKey = "~src";
+    roomData.addProperty(mediaResourceSourceKey, "http://localhost:8080/images/image1");
+    roomData.setWriteProperties(EntitySerializerProperties.serviceRoot(URI.create(BASE_URI)).
+        includeMetadata(true).build());
+
+    EdmEntitySet roomsSet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+    EdmEntityType roomType = roomsSet.getEntityType();
+    EdmMapping mapping = mock(EdmMapping.class);
+    when(roomType.getMapping()).thenReturn(mapping);
+    when(mapping.getMediaResourceSourceKey()).thenReturn(mediaResourceSourceKey);
+
+    ODataResponse response = new JsonSerializerDeserializer().writeEntry(roomsSet, roomData);
+    String jsonString = verifyResponse(response);
+    Gson gson = new Gson();
+    LinkedTreeMap<String, Object> jsonMap = gson.fromJson(jsonString, LinkedTreeMap.class);
+    jsonMap = (LinkedTreeMap<String, Object>) jsonMap.get("__metadata");
+
+    assertNull(jsonMap.get("media_src"));
+    assertNull(jsonMap.get("content_type"));
+    assertNull(jsonMap.get("edit_media"));
+  }
+
+  @SuppressWarnings("unchecked")
+  @Test
+  public void serializeWithCustomSrcAndTypeAttributeOnRoom() throws Exception {
+    Entity roomData = new Entity();
+    roomData.addProperty("Id", "1");
+    roomData.addProperty("Name", "Neu Schwanstein");
+    roomData.addProperty("Seats", new Integer(20));
+    roomData.addProperty("Version", new Integer(3));
+
+    String mediaResourceSourceKey = "~src";
+    roomData.addProperty(mediaResourceSourceKey, "http://localhost:8080/images/image1");
+    String mediaResourceMimeTypeKey = "~type";
+    roomData.addProperty(mediaResourceMimeTypeKey, "image/jpeg");
+    roomData.setWriteProperties(EntitySerializerProperties.serviceRoot(URI.create(BASE_URI)).
+        includeMetadata(true).build());
+
+    EdmEntitySet roomsSet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+    EdmEntityType roomType = roomsSet.getEntityType();
+    EdmMapping mapping = mock(EdmMapping.class);
+    when(roomType.getMapping()).thenReturn(mapping);
+    when(mapping.getMediaResourceSourceKey()).thenReturn(mediaResourceSourceKey);
+    when(mapping.getMediaResourceMimeTypeKey()).thenReturn(mediaResourceMimeTypeKey);
+
+    ODataResponse response = new JsonSerializerDeserializer().writeEntry(roomsSet, roomData);
+    String jsonString = verifyResponse(response);
+    Gson gson = new Gson();
+    LinkedTreeMap<String, Object> jsonMap = gson.fromJson(jsonString, LinkedTreeMap.class);
+    jsonMap = (LinkedTreeMap<String, Object>) jsonMap.get("__metadata");
+
+    assertNull(jsonMap.get("media_src"));
+    assertNull(jsonMap.get("content_type"));
+    assertNull(jsonMap.get("edit_media"));
+  }
+  
+  private String verifyResponse(final ODataResponse response) throws IOException {
+    assertNotNull(response);
+    assertNotNull(response.getEntity());
+    assertNull("EntitypProvider must not set content header", response.getContentHeader());
+
+    final String json = StringHelper.inputStreamToString((InputStream) response.getEntity());
+    assertNotNull(json);
+    return json;
+  }
+  
+  @Test
+  public void unbalancedPropertyEntryWithInlineEntry() throws Exception {
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+    Entity roomData = new Entity();
+    roomData.addProperty("Id", "1");
+    roomData.addProperty("Version", 1);
+    roomData.setWriteProperties(DEFAULT_PROPERTIES);
+    
+    Entity buildingData = new Entity();
+    buildingData.addProperty("Id", "1");
+    buildingData.addProperty("Name", "Building1");
+    roomData.addNavigation("nr_Building", buildingData);
+    
+    final ODataResponse response =
+        new JsonSerializerDeserializer().writeEntry(entitySet, roomData);
+    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("{\"Id\":\"1\",\"Version\":1,\"nr_Building\":{\"Id\":\"1\",\"Name\":\"Building1\"}}", json);
+  }
+  @Test
+  public void entryWithEmptyInlineEntry() throws Exception {
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+    Entity roomData = new Entity();
+    roomData.addProperty("Id", "1");
+    roomData.addProperty("Version", 1);
+    roomData.setWriteProperties(DEFAULT_PROPERTIES);
+    
+    Entity buildingData = new Entity();
+    roomData.addNavigation("nr_Building", buildingData);
+    
+    final ODataResponse response =
+        new JsonSerializerDeserializer().writeEntry(entitySet, roomData);
+    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("{\"Id\":\"1\",\"Version\":1,\"nr_Building\":"
+        + "{}}", json);
+  }
+  
+  @Test
+  public void entryWithEmptyInlineEntryWithKeyAutoGenFlag() throws Exception {
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+    Entity roomData = new Entity();
+    roomData.addProperty("Id", "1");
+    roomData.addProperty("Version", 1);
+    roomData.setWriteProperties(EntitySerializerProperties.serviceRoot(URI.create(BASE_URI)).
+        isKeyAutoGenerated(true).build());
+    
+    Entity buildingData = new Entity();
+    roomData.addNavigation("nr_Building", buildingData);
+    
+    final ODataResponse response =
+        new JsonSerializerDeserializer().writeEntry(entitySet, roomData);
+    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("{\"Id\":\"1\",\"Version\":1,\"nr_Building\":"
+        + "{}}", json);
+  }
+  
+  @Test
+  public void entryWithInlineEntryWithoutKey() throws Exception {
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+    Entity roomData = new Entity();
+    roomData.addProperty("Version", 1);
+    roomData.setWriteProperties(EntitySerializerProperties.serviceRoot(URI.create(BASE_URI)).
+        isKeyAutoGenerated(true).build());
+    
+    Entity buildingData = new Entity();
+    buildingData.addProperty("Name", "Building1");
+    roomData.addNavigation("nr_Building", buildingData);
+    
+    final ODataResponse response =
+        new JsonSerializerDeserializer().writeEntry(entitySet, roomData);
+    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("{\"Version\":1,\"nr_Building\":{\"Name\":\"Building1\"}}", json);
+  }
+  
+  @Test
+  public void entryWithInlineEntryWithoutKeyWithMetadata() throws Exception {
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+    Entity roomData = new Entity();
+    roomData.addProperty("Version", 1);
+    roomData.setWriteProperties(EntitySerializerProperties.serviceRoot(URI.create(BASE_URI)).
+        isKeyAutoGenerated(true).includeMetadata(true).build());
+    
+    Entity buildingData = new Entity();
+    buildingData.addProperty("Name", "Building1");
+    roomData.addNavigation("nr_Building", buildingData);
+    
+    final ODataResponse response =
+        new JsonSerializerDeserializer().writeEntry(entitySet, roomData);
+    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("{\"__metadata\":{\"id\":\"http://host:80/service/Rooms\","
+        + "\"uri\":\"http://host:80/service/Rooms('A')\",\"type\":\"RefScenario.Room\"},"
+        + "\"Version\":1,\"nr_Building\":{\"Name\":\"Building1\"}}", json);
+  }
+  
+  @Test
+  public void contentOnlyWithoutKeyWithoutSelectedProperties() throws Exception {
+    Entity employeeData = new Entity();
+    employeeData.addProperty("ManagerId", "1");
+    employeeData.addProperty("Age", new Integer(52));
+    employeeData.addProperty("RoomId", "1");
+    employeeData.addProperty("TeamId", "42");
+
+    employeeData.setWriteProperties(
+        EntitySerializerProperties.serviceRoot(URI.create(BASE_URI)).build());
+    
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+
+    try {
+      new JsonSerializerDeserializer().writeEntry(entitySet, employeeData);
+    } catch (EntityProviderProducerException e) {
+      assertTrue(e.getMessage().contains("The metadata do not allow a null value for property 'EmployeeId'"));
+    }
+  }
+  
+  @Test
+  public void testWithoutCompositeKey() throws Exception {
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getEntityContainer("Container2").getEntitySet("Photos");
+    
+    Entity photoData = new Entity();
+    photoData.addProperty("Name", "Mona Lisa");
+    photoData.setWriteProperties(
+        EntitySerializerProperties.serviceRoot(URI.create(BASE_URI)).build());
+
+    try {
+      new JsonSerializerDeserializer().writeEntry(entitySet, photoData);
+    } catch (EntityProviderProducerException e) {
+      assertTrue(e.getMessage().contains("The metadata do not allow a null value for property 'Id'"));
+    }
+  }
+  
+  @Test
+  public void testWithoutCompositeKeyWithOneKeyNull() throws Exception {
+    Edm edm = MockFacade.getMockEdm();
+    EdmEntitySet entitySet = edm.getEntityContainer("Container2").getEntitySet("Photos");
+    
+    Entity photoData = new Entity();
+    photoData.addProperty("Name", "Mona Lisa");
+    photoData.addProperty("Id", Integer.valueOf(1));
+    photoData.setWriteProperties(
+        EntitySerializerProperties.serviceRoot(URI.create(BASE_URI)).build());
+    
+    EdmTyped typeProperty = edm.getEntityContainer("Container2").getEntitySet("Photos").
+        getEntityType().getProperty("Type");
+    EdmFacets facets = mock(EdmFacets.class);
+    when(facets.getConcurrencyMode()).thenReturn(EdmConcurrencyMode.Fixed);
+    when(facets.getMaxLength()).thenReturn(3);
+    when(((EdmProperty) typeProperty).getFacets()).thenReturn(facets);
+
+    try {
+      new JsonSerializerDeserializer().writeEntry(entitySet, photoData);
+    } catch (EntityProviderProducerException e) {
+      assertTrue(e.getMessage().contains("The metadata do not allow a null value for property 'Type'"));
+    }
+  }
+  
+  @Test
+  public void testExceptionWithNonNullablePropertyIsNull() throws Exception {
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Organizations");
+    EdmProperty nameProperty = (EdmProperty) entitySet.getEntityType().getProperty("Name");
+    EdmFacets facets = nameProperty.getFacets();
+    when(facets.isNullable()).thenReturn(new Boolean(false));
+    
+    Entity orgData = new Entity();
+    orgData.addProperty("Id", "1");
+    orgData.setWriteProperties(
+        EntitySerializerProperties.serviceRoot(URI.create(BASE_URI)).build());
+    try {
+      new JsonSerializerDeserializer().writeEntry(entitySet, orgData);
+    } catch (EntityProviderProducerException e) {
+      assertTrue(e.getMessage().contains("The metadata do not allow a null value for property 'Name'"));
+    }
+  }
+  
+  private InputStream createStreamReader(final String xml) throws
+  XMLStreamException, UnsupportedEncodingException {
+    return new ByteArrayInputStream(xml.getBytes("UTF-8"));
+  }
+  
+  @Test
+  public void deepInsertEndToEnd() throws Exception {
+    XmlMetadataDeserializer parser = new XmlMetadataDeserializer();
+    String xml = readFile("metadataForDeepInsert.xml");
+    InputStream reader = createStreamReader(xml);
+    EdmDataServices result = parser.readMetadata(reader, true);
+    assertEquals(1, result.getEdm().getSchemas().size());
+    ClientEdm edm = result.getEdm();
+    
+    Entity descMap = new Entity();
+    descMap.addProperty("Product", "CRPROD2");
+    descMap.addProperty("Language", "ES");
+    descMap.addProperty("ProductDescription", "Hola2");
+    EntityCollection descList =  new EntityCollection();
+
+    descList.addEntity(descMap);
+
+    Entity prodCreateFakeMap = new Entity();
+    prodCreateFakeMap.addProperty("Product", "CRPROD2");
+    prodCreateFakeMap.addProperty("ProductType", "HALB");
+    prodCreateFakeMap.addProperty("BaseUnit", "PC");
+
+    prodCreateFakeMap.addNavigation("to_Description", descList);
+   
+    EntitySerializerProperties properties = EntitySerializerProperties
+        .serviceRoot(URI.create(BASE_URI)).build();
+    prodCreateFakeMap.setWriteProperties(properties);
+    JsonSerializerDeserializer provider = new JsonSerializerDeserializer();
+    ODataResponse response =provider
+        .writeEntry(edm.getDefaultEntityContainer().getEntitySet("A_Product"), prodCreateFakeMap);
+
+    assertNotNull(response);
+    assertNotNull(response.getEntity());
+
+    final String json = StringHelper.inputStreamToString((InputStream) response.getEntity());
+    assertNotNull(json);
+    assertEquals("{\"Product\":\"CRPROD2\",\"BaseUnit\":\"PC\",\"ProductType\":\"HALB\","
+        + "\"to_Description\":[{\"Product\":\"CRPROD2\",\"Language\":\"ES\",\"ProductDescription\":\"Hola2\"}]}", json);
+ 
+  }
+  
+  protected String readFile(final String filename) throws IOException {
+    InputStream in = getFileAsStream(filename);
+
+    byte[] tmp = new byte[8192];
+    int count = in.read(tmp);
+    StringBuilder b = new StringBuilder();
+    while (count >= 0) {
+      b.append(new String(tmp, 0, count));
+      count = in.read(tmp);
+    }
+
+    return b.toString();
+  }
+  protected InputStream getFileAsStream(final String filename) throws IOException {
+    InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream(filename);
+    if (in == null) {
+      throw new IOException("Requested file '" + filename + "' was not found.");
+    }
+    return in;
+  }
+  
+  @Test
+  public void testExceptionWithNonNullablePropertyIsNull1() throws Exception {
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Organizations");
+    EdmProperty kindProperty = (EdmProperty) entitySet.getEntityType().getProperty("Kind");
+    EdmFacets facets = kindProperty.getFacets();
+    when(facets.isNullable()).thenReturn(new Boolean(false));
+    
+    EdmProperty nameProperty = (EdmProperty) entitySet.getEntityType().getProperty("Name");
+    when(nameProperty.getFacets()).thenReturn(null);
+    
+    Entity orgData = new Entity();
+    orgData.addProperty("Id", "1");
+    orgData.addProperty("Name", "Org1");
+    orgData.setWriteProperties(
+        EntitySerializerProperties.serviceRoot(URI.create(BASE_URI)).build());
+    try {
+      new JsonSerializerDeserializer().writeEntry(entitySet, orgData);
+    } catch (EntityProviderProducerException e) {
+      assertTrue(e.getMessage().contains("The metadata do not allow a null value for property 'Kind'"));
+    }
+  }
+  
+  @Test
+  public void testExceptionWithNonNullablePropertyIsNull2() throws Exception {
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Organizations");
+    EdmProperty kindProperty = (EdmProperty) entitySet.getEntityType().getProperty("Kind");
+    EdmFacets facets = kindProperty.getFacets();
+    when(facets.isNullable()).thenReturn(new Boolean(false));
+    
+    EdmProperty nameProperty = (EdmProperty) entitySet.getEntityType().getProperty("Name");
+    EdmFacets facets1 = nameProperty.getFacets();
+    when(facets1.isNullable()).thenReturn(new Boolean(false));
+     
+    Entity orgData = new Entity();
+    orgData.addProperty("Id", "1");
+    orgData.addProperty("Name", "Org1");
+    orgData.setWriteProperties(
+        EntitySerializerProperties.serviceRoot(URI.create(BASE_URI)).build());
+    try {
+      new JsonSerializerDeserializer().writeEntry(entitySet, orgData);
+    } catch (EntityProviderProducerException e) {
+      assertTrue(e.getMessage().contains("do not allow to format the value 'Org1' for property 'Name'."));
+    }
+  }
+}


[13/24] olingo-odata2 git commit: [OLINGO-1253]Client Module for Olingo v2

Posted by ar...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/deserializer/XmlEntityDeserializerTest.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/deserializer/XmlEntityDeserializerTest.java b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/deserializer/XmlEntityDeserializerTest.java
new file mode 100644
index 0000000..caf05da
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/ep/deserializer/XmlEntityDeserializerTest.java
@@ -0,0 +1,2461 @@
+/*******************************************************************************
+ * 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.client.core.ep.deserializer;
+
+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.io.InputStream;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.TimeZone;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.apache.olingo.odata2.api.commons.HttpContentType;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmFacets;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+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.client.api.ep.DeserializerProperties;
+import org.apache.olingo.odata2.client.api.ep.EntityStream;
+import org.apache.olingo.odata2.client.api.ep.callback.OnDeserializeInlineContent;
+import org.apache.olingo.odata2.testutil.helper.StringHelper;
+import org.apache.olingo.odata2.testutil.mock.MockFacade;
+import org.junit.Assert;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+/**
+ *  
+ */
+public class XmlEntityDeserializerTest extends AbstractXmlDeserializerTest {
+
+  public XmlEntityDeserializerTest(final StreamWriterImplType type) {
+    super(type);
+  }
+
+  private static final Logger LOG = Logger.getLogger(XmlEntityDeserializerTest.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>";
+
+  @Test
+  public void readContentOnlyEmployee() throws Exception {
+    // prepare
+    String content = readFile("EmployeeContentOnly.xml");
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+    InputStream contentBody = createContentAsStream(content);
+    EntityStream stream = new EntityStream();
+    stream.setReadProperties(DeserializerProperties.init().build());
+    stream.setContent(contentBody);
+    // execute
+    XmlEntityDeserializer xec = new XmlEntityDeserializer();
+    ODataEntry result =
+        xec.readEntry(entitySet, stream);
+
+    // verify
+    assertEquals(9, result.getProperties().size());
+  }
+
+  @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);
+    EntityStream stream = new EntityStream();
+    DeserializerProperties consumerProperties = DeserializerProperties.init()
+        .build();
+    stream.setReadProperties(consumerProperties);
+    stream.setContent(reqContent);
+    // execute
+    XmlEntityDeserializer xec = new XmlEntityDeserializer();
+
+    ODataFeed feed = xec.readFeed(entitySet, stream);
+    assertNotNull(feed);
+
+    FeedMetadata feedMetadata = feed.getFeedMetadata();
+    assertNotNull(feedMetadata);
+
+    String deltaLink = feedMetadata.getDeltaLink();
+    // Null means no deltaLink found
+    assertNotNull(deltaLink);
+
+    assertEquals("http://thisisadeltalink", deltaLink);
+  }
+
+  @Test
+  public void testReadSkipTag() throws Exception {
+    // prepare
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+    InputStream contentBody = createContentAsStream(EMPLOYEE_1_XML
+        .replace("<title type=\"text\">Walter Winter</title>",
+            "<title type=\"text\"><title>Walter Winter</title></title>"));
+    // execute
+    EntityStream stream = new EntityStream();
+    stream.setContent(contentBody);
+    stream.setReadProperties(DeserializerProperties.init().build());
+    XmlEntityDeserializer xec = new XmlEntityDeserializer();
+    ODataEntry result = xec.readEntry(entitySet, stream);
+    // verify
+    String id = result.getMetadata().getId();
+    assertEquals("http://localhost:19000/Employees('1')", id);
+    Map<String, Object> properties = result.getProperties();
+    assertEquals(9, properties.size());
+  }
+
+  @Test
+  public void readContentOnlyRoom() throws Exception {
+    // prepare
+    String content = readFile("RoomContentOnly.xml");
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+    InputStream contentBody = createContentAsStream(content);
+
+    // execute
+    XmlEntityDeserializer xec = new XmlEntityDeserializer();
+    EntityStream stream = new EntityStream();
+    stream.setReadProperties(DeserializerProperties.init().build());
+    stream.setContent(contentBody);
+    ODataEntry result =
+        xec.readEntry(entitySet, stream);
+
+    // verify
+    assertEquals(4, result.getProperties().size());
+  }
+
+  @Test
+  public void readContentOnlyEmployeeWithNavigationLink() throws Exception {
+    // prepare
+    String content = readFile("EmployeeContentOnlyWithNavigationLink.xml");
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+    InputStream contentBody = createContentAsStream(content);
+
+    // execute
+    XmlEntityDeserializer xec = new XmlEntityDeserializer();
+    EntityStream stream = new EntityStream();
+    stream.setReadProperties(DeserializerProperties.init().build());
+    stream.setContent(contentBody);
+    ODataEntry result =
+        xec.readEntry(entitySet, stream);
+
+    // verify
+    assertEquals(9, result.getProperties().size());
+    List<String> associationUris = result.getMetadata().getAssociationUris("ne_Manager");
+    assertEquals(1, associationUris.size());
+    assertEquals("Managers('1')", associationUris.get(0));
+  }
+
+  @Test
+  public void readContentOnlyRoomWithNavigationLink() throws Exception {
+    // prepare
+    String content = readFile("RoomContentOnlyWithNavigationLink.xml");
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+    InputStream contentBody = createContentAsStream(content);
+
+    // execute
+    XmlEntityDeserializer xec = new XmlEntityDeserializer();
+    EntityStream stream = new EntityStream();
+    stream.setReadProperties(DeserializerProperties.init().build());
+    stream.setContent(contentBody);
+    ODataEntry result =
+        xec.readEntry(entitySet, stream);
+
+    // verify
+    assertEquals(4, result.getProperties().size());
+    List<String> associationUris = result.getMetadata().getAssociationUris("nr_Building");
+    assertEquals(1, associationUris.size());
+    assertEquals("Buildings('1')", associationUris.get(0));
+  }
+
+  /** Teams('1')?$expand=nt_Employees */
+  @SuppressWarnings("unchecked")
+  @Test
+  public void readTeamWithInlineContent() throws Exception {
+    // prepare
+    String content = readFile("expanded_team.xml");
+    assertNotNull(content);
+
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+    InputStream reqContent = createContentAsStream(content);
+
+    // execute
+    XmlEntityDeserializer xec = new XmlEntityDeserializer();
+    EntityStream stream = new EntityStream();
+    stream.setReadProperties(DeserializerProperties.init().build());
+    stream.setContent(reqContent);
+
+    ODataEntry entry = xec.readEntry(entitySet, stream);
+    // 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"));
+
+    assertNotNull(properties.get("nt_Employees"));
+    ODataFeed employeeFeed = (ODataFeed) properties.get("nt_Employees");
+    List<ODataEntry> employees = employeeFeed.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"));
+  }
+
+  @Test
+  public void readExpandedTeam() throws Exception {
+    // prepare
+    String content = readFile("expanded_team.xml");
+    assertNotNull(content);
+
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+    InputStream reqContent = createContentAsStream(content);
+    EntityStream stream = new EntityStream();
+    stream.setReadProperties(DeserializerProperties.init().build());
+    stream.setContent(reqContent);
+
+    // execute
+    XmlEntityDeserializer xec = new XmlEntityDeserializer();
+
+    ODataEntry entry = xec.readEntry(entitySet, stream);
+    // 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"));
+    assertNotNull(properties.get("nt_Employees"));
+    //
+    assertNotNull(entry);
+
+    ODataFeed employeeFeed = (ODataFeed) properties.get("nt_Employees");
+    List<ODataEntry> employees = (List<ODataEntry>) employeeFeed.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
+    XmlEntityDeserializer xec = new XmlEntityDeserializer();
+    OnDeserializeInlineContent callback = new Callback();
+    DeserializerProperties consumerProperties = DeserializerProperties.init().callback(callback).build();
+
+    EntityStream stream = new EntityStream();
+    stream.setContent(reqContent);
+    stream.setReadProperties(consumerProperties);
+
+    ODataEntry entry = xec.readEntry(entitySet, stream);
+    // 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"));
+
+    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 */
+  @SuppressWarnings("unchecked")
+  @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
+    XmlEntityDeserializer xec = new XmlEntityDeserializer();
+    DeserializerProperties consumerProperties = DeserializerProperties.init()
+        .build();
+
+    EntityStream stream = new EntityStream();
+    stream.setContent(reqContent);
+    stream.setReadProperties(consumerProperties);
+
+    ODataEntry entry = xec.readEntry(entitySet, stream);
+    // 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"));
+    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"));
+  }
+
+  /** 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
+    XmlEntityDeserializer xec = new XmlEntityDeserializer();
+    DeserializerProperties consumerProperties = DeserializerProperties.init().build();
+    EntityStream stream = new EntityStream();
+    stream.setContent(reqContent);
+    stream.setReadProperties(consumerProperties);
+
+    ODataEntry entry = xec.readEntry(entitySet, stream);
+    // 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
+  public void readWithDoubleInlineContentAndResend() throws Exception {
+    // prepare
+    String content = readFile("double_expanded_team.xml");
+    assertNotNull(content);
+
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+    InputStream reqContent = createContentAsStream(content);
+    EntityStream stream = new EntityStream();
+    stream.setContent(reqContent);
+    DeserializerProperties consumerProperties = DeserializerProperties.init().build();
+    stream.setReadProperties(consumerProperties);
+
+    // execute
+    XmlEntityDeserializer xec = new XmlEntityDeserializer();
+    ODataEntry entry = xec.readEntry(entitySet, stream);
+
+    // 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 employeeFeed = (ODataFeed) properties.get("nt_Employees");
+    List<ODataEntry> employees = (List<ODataEntry>) employeeFeed.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 */
+  @SuppressWarnings("unchecked")
+  @Test
+  public void readWithDoubleInlineContents() throws Exception {
+    // prepare
+    String content = readFile("double_expanded_team.xml");
+    assertNotNull(content);
+
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+    InputStream reqContent = createContentAsStream(content);
+    EntityStream stream = new EntityStream();
+    stream.setContent(reqContent);
+    stream.setReadProperties(DeserializerProperties.init().build());
+
+    // execute
+    XmlEntityDeserializer xec = new XmlEntityDeserializer();
+    ODataEntry entry = xec.readEntry(entitySet, stream);
+
+    // 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");
+    assertNotNull(employeesFeed);
+    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");
+    assertNotNull(inlinedTeam);
+    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);
+    EntityStream stream = new EntityStream();
+    stream.setContent(reqContent);
+    stream.setReadProperties(DeserializerProperties.init().build());
+
+    // execute
+    XmlEntityDeserializer xec = new XmlEntityDeserializer();
+    ODataEntry entry = xec.readEntry(entitySet, stream);
+
+    // 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);
+    EntityStream stream = new EntityStream();
+    stream.setContent(reqContent);
+    stream.setReadProperties(DeserializerProperties.init().build());
+
+    // execute
+    XmlEntityDeserializer xec = new XmlEntityDeserializer();
+    ODataEntry employee = xec.readEntry(entitySet, stream);
+
+    // validate
+    assertNotNull(employee);
+    Map<String, Object> properties = employee.getProperties();
+    assertEquals("1", properties.get("EmployeeId"));
+    assertEquals("Walter Winter", properties.get("EmployeeName"));
+    EntryMetadata employeeMetadata = employee.getMetadata();
+    assertNotNull(employeeMetadata);
+    assertEquals("W/\"1\"", employeeMetadata.getEtag());
+
+    // Inline
+    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"));
+    EntryMetadata roomMetadata = room.getMetadata();
+    assertNotNull(roomMetadata);
+    assertEquals("W/1", roomMetadata.getEtag());
+  }
+
+  /**
+   * 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);
+    EntityStream stream = new EntityStream();
+    stream.setContent(reqContent);
+    stream.setReadProperties(DeserializerProperties.init().build());
+
+    // execute
+    XmlEntityDeserializer xec = new XmlEntityDeserializer();
+    ODataEntry entry = xec.readEntry(entitySet, stream);
+
+    // 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 {@link com.sap.core.odata.api.edm.EdmMultiplicity#ONE EdmMultiplicity#ONE}).
+   */
+  @Test
+  public void readWithInlineContentEmployeeNullRoomEntry() throws Exception {
+
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+    InputStream reqContent = createContentAsStream(EMPLOYEE_1_NULL_ROOM_XML);
+    EntityStream stream = new EntityStream();
+    stream.setContent(reqContent);
+    stream.setReadProperties(DeserializerProperties.init().build());
+
+    // execute
+    XmlEntityDeserializer xec = new XmlEntityDeserializer();
+    ODataEntry entry = xec.readEntry(entitySet, stream);
+
+    // 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 {@link com.sap.core.odata.api.edm.EdmMultiplicity#ONE EdmMultiplicity#ONE}).
+   */
+  @Test
+  public void readWithInlineContentEmployeeNullRoomEntrySpecialXmlFormat() throws Exception {
+
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+    InputStream reqContent = createContentAsStream(EMPLOYEE_1_NULL_ROOM_XML, true);
+    EntityStream stream = new EntityStream();
+    stream.setContent(reqContent);
+    stream.setReadProperties(DeserializerProperties.init().build());
+
+    // execute
+    XmlEntityDeserializer xec = new XmlEntityDeserializer();
+    ODataEntry entry = xec.readEntry(entitySet, stream);
+
+    // 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
+   * (which has {@link com.sap.core.odata.api.edm.EdmMultiplicity#MANY EdmMultiplicity#MANY}).
+   */
+  @Test
+  public void readWithInlineContentRoomNullEmployeesEntry() throws Exception {
+
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+    InputStream reqContent = createContentAsStream(ROOM_1_NULL_EMPLOYEE_XML);
+    EntityStream stream = new EntityStream();
+    stream.setContent(reqContent);
+    stream.setReadProperties(DeserializerProperties.init().build());
+
+    // execute
+    XmlEntityDeserializer xec = new XmlEntityDeserializer();
+    ODataEntry entry = xec.readEntry(entitySet, stream);
+
+    // 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);
+    EntityStream stream = new EntityStream();
+    stream.setContent(reqContent);
+    stream.setReadProperties(DeserializerProperties.init().build());
+
+    // execute
+    XmlEntityDeserializer xec = new XmlEntityDeserializer();
+    ODataEntry result = xec.readEntry(entitySet, stream);
+
+    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);
+    EntityStream stream = new EntityStream();
+    stream.setContent(reqContent);
+    stream.setReadProperties(DeserializerProperties.init().build());
+
+    // execute
+    XmlEntityDeserializer xec = new XmlEntityDeserializer();
+    ODataEntry result = xec.readEntry(entitySet, stream);
+    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);
+    EntityStream stream = new EntityStream();
+    stream.setContent(reqContent);
+    stream.setReadProperties(DeserializerProperties.init().build());
+
+    // execute
+    XmlEntityDeserializer xec = new XmlEntityDeserializer();
+    ODataEntry result = xec.readEntry(entitySet, stream);
+    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);
+    EntityStream stream = new EntityStream();
+    stream.setContent(reqContent);
+    stream.setReadProperties(DeserializerProperties.init().build());
+
+    // execute
+    XmlEntityDeserializer xec = new XmlEntityDeserializer();
+    ODataEntry result = xec.readEntry(entitySet, stream);
+    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);
+    EntityStream stream = new EntityStream();
+    stream.setContent(reqContent);
+    stream.setReadProperties(DeserializerProperties.init().build());
+
+    // execute
+    XmlEntityDeserializer xec = new XmlEntityDeserializer();
+    ODataEntry result = xec.readEntry(entitySet, stream);
+    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);
+
+    EntityStream stream = new EntityStream();
+    stream.setContent(reqContent);
+    stream.setReadProperties(DeserializerProperties.init().build());
+
+    // execute
+    XmlEntityDeserializer xec = new XmlEntityDeserializer();
+    ODataEntry result = xec.readEntry(entitySet, stream);
+    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);
+    EntityStream stream = new EntityStream();
+    stream.setContent(reqContent);
+    stream.setReadProperties(DeserializerProperties.init().build());
+
+    // execute
+    XmlEntityDeserializer xec = new XmlEntityDeserializer();
+    ODataEntry result = xec.readEntry(entitySet, stream);
+    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);
+    EntityStream stream = new EntityStream();
+    stream.setContent(reqContent);
+    stream.setReadProperties(DeserializerProperties.init().build());
+
+    // execute
+    XmlEntityDeserializer xec = new XmlEntityDeserializer();
+    ODataEntry result = xec.readEntry(entitySet, stream);
+    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);
+    XmlEntityDeserializer xec = new XmlEntityDeserializer();
+    EntityStream stream = new EntityStream();
+    stream.setContent(reqContent);
+    stream.setReadProperties(DeserializerProperties.init().build());
+
+    // execute
+    ODataEntry result = xec.readEntry(entitySet, stream);
+    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);
+    EntityStream stream = new EntityStream();
+    stream.setContent(reqContent);
+    stream.setReadProperties(DeserializerProperties.init().build());
+
+    // execute
+    XmlEntityDeserializer xec = new XmlEntityDeserializer();
+    ODataEntry result = xec.readEntry(entitySet, stream);
+    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);
+    EntityStream stream = new EntityStream();
+    stream.setContent(reqContent);
+    stream.setReadProperties(DeserializerProperties.init().build());
+
+    // execute
+    XmlEntityDeserializer xec = new XmlEntityDeserializer();
+    ODataEntry result = xec.readEntry(entitySet, stream);
+    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);
+    EntityStream stream = new EntityStream();
+    stream.setContent(reqContent);
+    stream.setReadProperties(DeserializerProperties.init().build());
+
+    // execute
+    XmlEntityDeserializer xec = new XmlEntityDeserializer();
+    ODataEntry result = xec.readEntry(entitySet, stream);
+    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 {
+      EntityStream stream = new EntityStream();
+      stream.setContent(reqContent);
+      stream.setReadProperties(DeserializerProperties.init().build());
+
+      // execute
+      XmlEntityDeserializer xec = new XmlEntityDeserializer();
+      ODataEntry result =
+          xec.readEntry(entitySet, stream);
+      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);
+
+    EntityStream stream = new EntityStream();
+    stream.setContent(contentBody);
+    stream.setReadProperties(DeserializerProperties.init().build());
+
+    // execute
+    XmlEntityDeserializer xec = new XmlEntityDeserializer();
+    ODataEntry result = xec.readEntry(entitySet, stream);
+    // 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);
+
+    EntityStream stream = new EntityStream();
+    stream.setContent(contentBody);
+    stream.setReadProperties(DeserializerProperties.init().build());
+
+    // execute
+    XmlEntityDeserializer xec = new XmlEntityDeserializer();
+    ODataEntry result = xec.readEntry(entitySet, stream);
+    // 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);
+    EntityStream stream = new EntityStream();
+    stream.setContent(contentAsStream);
+    stream.setReadProperties(DeserializerProperties.init().build());
+
+    // execute
+    XmlEntityDeserializer xec = new XmlEntityDeserializer();
+    ODataFeed feedResult = xec.readFeed(entitySet, stream);
+    // 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);
+    EntityStream stream = new EntityStream();
+    stream.setContent(contentAsStream);
+    stream.setReadProperties(DeserializerProperties.init().build());
+
+    // execute
+    XmlEntityDeserializer xec = new XmlEntityDeserializer();
+    ODataFeed feedResult = xec.readFeed(entitySet, stream);
+    // 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);
+    EntityStream stream = new EntityStream();
+    stream.setContent(contentBody);
+    stream.setReadProperties(DeserializerProperties.init().build());
+
+    // execute
+    XmlEntityDeserializer xec = new XmlEntityDeserializer();
+    ODataEntry result = xec.readEntry(entitySet, stream);
+    // 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));
+    EntityStream stream = new EntityStream();
+    stream.setContent(contentBody);
+    stream.setReadProperties(DeserializerProperties.init().build());
+
+    // execute
+    XmlEntityDeserializer xec = new XmlEntityDeserializer();
+    ODataEntry result = xec.readEntry(entitySet, stream);
+    // 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 '

<TRUNCATED>

[05/24] olingo-odata2 git commit: [OLINGO-1253]Client Module for Olingo v2

Posted by ar...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/uri/UriParserTest.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/uri/UriParserTest.java b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/uri/UriParserTest.java
new file mode 100644
index 0000000..50d0c5e
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/java/org/apache/olingo/odata2/client/core/uri/UriParserTest.java
@@ -0,0 +1,1132 @@
+package org.apache.olingo.odata2.client.core.uri;
+
+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 static org.junit.Assert.fail;
+import static org.mockito.Mockito.when;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.commons.InlineCount;
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeKind;
+import org.apache.olingo.odata2.api.edm.EdmTypeKind;
+import org.apache.olingo.odata2.api.exception.MessageReference;
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.api.exception.ODataMessageException;
+import org.apache.olingo.odata2.api.uri.KeyPredicate;
+import org.apache.olingo.odata2.api.uri.PathSegment;
+import org.apache.olingo.odata2.api.uri.UriInfo;
+import org.apache.olingo.odata2.api.uri.UriNotMatchingException;
+import org.apache.olingo.odata2.api.uri.UriParser;
+import org.apache.olingo.odata2.api.uri.UriSyntaxException;
+import org.apache.olingo.odata2.client.api.ODataClient;
+import org.apache.olingo.odata2.core.uri.UriInfoImpl;
+import org.apache.olingo.odata2.core.uri.UriParserImpl;
+import org.apache.olingo.odata2.core.uri.UriType;
+import org.apache.olingo.odata2.testutil.mock.MockFacade;
+import org.junit.Before;
+import org.junit.Test;
+
+public class UriParserTest {
+
+  private Edm edm;
+
+  @Before
+  public void getEdm() throws ODataException {
+    edm = MockFacade.getMockEdm();
+  }
+  
+  @Test
+  public void copyPathSegmentsTest() throws Exception {
+    List<PathSegment> pathSegments = new ArrayList<PathSegment>();
+    pathSegments.add(UriParser.createPathSegment("$metadata", null));
+    UriInfo result = new UriParserImpl(edm).parse(pathSegments, Collections.<String, String> emptyMap());
+    assertNotNull(result);
+    assertEquals(1, pathSegments.size());
+    assertEquals("$metadata", pathSegments.get(0).getPath());
+  }
+  
+  @Test
+  public void copyPathSegmentsTestEncoded() throws Exception {
+    List<PathSegment> pathSegments = new ArrayList<PathSegment>();
+    pathSegments.add(UriParser.createPathSegment("%24metadata", null));
+    UriInfoImpl result = (UriInfoImpl) new UriParserImpl(edm).parse(pathSegments,
+        Collections.<String, String> emptyMap());
+    assertNotNull(result);
+    assertEquals(UriType.URI8, result.getUriType());
+  }
+  
+  @Test
+  public void parseNonsense() throws Exception {
+    parseWrongUri("/bla", UriNotMatchingException.NOTFOUND);
+  }
+
+  @Test
+  public void parseServiceDocument() throws Exception {
+    UriInfoImpl result = parse("/");
+    assertEquals(UriType.URI0, result.getUriType());
+
+    result = parse("");
+    assertEquals(UriType.URI0, result.getUriType());
+
+    result =
+        (UriInfoImpl) new UriParserImpl(edm).parse(Collections.<PathSegment> emptyList(), Collections
+            .<String, String> emptyMap());
+    assertEquals(UriType.URI0, result.getUriType());
+  }
+
+  @Test
+  public void parseMetadata() throws Exception {
+    UriInfoImpl result = parse("/$metadata");
+    assertEquals(UriType.URI8, result.getUriType());
+  }
+
+  @Test
+  public void parseMetadataError() throws Exception {
+    parseWrongUri("/$metadata/somethingwrong", UriSyntaxException.MUSTBELASTSEGMENT);
+  }
+
+  @Test
+  public void parseBatch() throws Exception {
+    UriInfoImpl result = parse("/$batch");
+    assertEquals(UriType.URI9, result.getUriType());
+  }
+
+  @Test
+  public void parseBatchError() throws Exception {
+    parseWrongUri("/$batch/somethingwrong", UriSyntaxException.MUSTBELASTSEGMENT);
+  }
+
+  @Test
+  public void parseSomethingEntitySet() throws Exception {
+    parseWrongUri("/somethingwrong", UriNotMatchingException.NOTFOUND);
+  }
+
+  @Test
+  public void parseContainerWithoutEntitySet() throws Exception {
+    parseWrongUri("Container1.", UriNotMatchingException.MATCHPROBLEM);
+  }
+
+  @Test
+  public void parseEmployeesEntitySet() throws Exception {
+    UriInfoImpl result = parse("/Employees");
+    assertNull(result.getEntityContainer().getName());
+    assertEquals("Employees", result.getTargetEntitySet().getName());
+    assertEquals(UriType.URI1, result.getUriType());
+  }
+
+  @Test
+  public void parseEmployeesEntitySetParenthesesCount() throws Exception {
+    UriInfoImpl result = parse("/Employees()/$count");
+    assertNull(result.getEntityContainer().getName());
+    assertEquals("Employees", result.getTargetEntitySet().getName());
+    assertEquals(UriType.URI15, result.getUriType());
+    assertTrue(result.isCount());
+  }
+
+  @Test
+  public void parseEmployeesEntitySetParenthesesCountNotLast() throws Exception {
+    parseWrongUri("/Employees()/$count/somethingwrong", UriSyntaxException.MUSTBELASTSEGMENT);
+  }
+
+  @Test
+  public void parseEmployeesEntitySetParentheses() throws Exception {
+    UriInfoImpl result = parse("/Employees()");
+    assertNull(result.getEntityContainer().getName());
+    assertEquals("Employees", result.getTargetEntitySet().getName());
+    assertEquals(UriType.URI1, result.getUriType());
+  }
+
+  @Test
+  public void finalEmptySegment() throws Exception {
+    UriInfoImpl result = parse("Employees()/");
+    assertEquals("Employees", result.getTargetEntitySet().getName());
+    assertEquals(UriType.URI1, result.getUriType());
+  }
+
+  @Test
+  public void parseWrongEntities() throws Exception {
+    parseWrongUri("//", UriSyntaxException.EMPTYSEGMENT);
+    parseWrongUri("/Employees%20()", UriNotMatchingException.NOTFOUND);
+    parseWrongUri("Employees%28%29", UriNotMatchingException.NOTFOUND);
+    parseWrongUri("/Employees()%2F", UriNotMatchingException.MATCHPROBLEM);
+    parseWrongUri("/Employees()/somethingwrong", UriSyntaxException.ENTITYSETINSTEADOFENTITY);
+    parseWrongUri("/Employees/somethingwrong", UriSyntaxException.ENTITYSETINSTEADOFENTITY);
+    parseWrongUri("//Employees", UriSyntaxException.EMPTYSEGMENT);
+    parseWrongUri("Employees//", UriSyntaxException.EMPTYSEGMENT);
+  }
+
+  @Test
+  public void parseEmployeesEntityWithKey() throws Exception {
+    UriInfoImpl result = parse("/Employees('1')");
+    assertNull(result.getEntityContainer().getName());
+    assertEquals("Employees", result.getTargetEntitySet().getName());
+    assertEquals(UriType.URI2, result.getUriType());
+
+    assertEquals(1, result.getKeyPredicates().size());
+    assertEquals("1", result.getKeyPredicates().get(0).getLiteral());
+    assertEquals("EmployeeId", result.getKeyPredicates().get(0).getProperty().getName());
+  }
+
+  @Test
+  public void parseEmployeesEntityWithKeyWithComma() throws Exception {
+    UriInfoImpl result = parse("/Employees('1,2')");
+    assertNull(result.getEntityContainer().getName());
+    assertEquals("Employees", result.getTargetEntitySet().getName());
+    assertEquals(UriType.URI2, result.getUriType());
+
+    assertEquals(1, result.getKeyPredicates().size());
+    assertEquals("1,2", result.getKeyPredicates().get(0).getLiteral());
+    assertEquals("EmployeeId", result.getKeyPredicates().get(0).getProperty().getName());
+  }
+
+  @Test
+  public void parseEmployeesEntityWithKeyWithSquoteInString() throws Exception {
+    UriInfoImpl result = parse("/Employees('1''2')");
+    assertNull(result.getEntityContainer().getName());
+    assertEquals("Employees", result.getTargetEntitySet().getName());
+    assertEquals(UriType.URI2, result.getUriType());
+
+    assertEquals(1, result.getKeyPredicates().size());
+    assertEquals("1'2", result.getKeyPredicates().get(0).getLiteral());
+    assertEquals("EmployeeId", result.getKeyPredicates().get(0).getProperty().getName());
+  }
+
+
+  @Test
+  public void parseEmployeesEntityWithKeyEncoded() throws Exception {
+    UriInfoImpl result = parse("/%45mployees('1')");
+    assertNull(result.getEntityContainer().getName());
+    assertEquals("Employees", result.getTargetEntitySet().getName());
+    assertEquals(UriType.URI2, result.getUriType());
+
+    assertEquals(1, result.getKeyPredicates().size());
+    assertEquals("1", result.getKeyPredicates().get(0).getLiteral());
+    assertEquals("EmployeeId", result.getKeyPredicates().get(0).getProperty().getName());
+  }
+  
+  @Test
+  public void parseEmployeesEntity() throws Exception {
+    UriInfoImpl result = parse("/Employees('1')");
+    assertNull(result.getEntityContainer().getName());
+    assertEquals("Employees", result.getTargetEntitySet().getName());
+    assertEquals(UriType.URI2, result.getUriType());
+
+    assertEquals(1, result.getKeyPredicates().size());
+    assertEquals("1", result.getKeyPredicates().get(0).getLiteral());
+    assertEquals("EmployeeId", result.getKeyPredicates().get(0).getProperty().getName());
+  }
+
+  @Test
+  public void parseEmployeesEntityWithExplicitKey() throws Exception {
+    UriInfoImpl result = parse("/Employees(EmployeeId='1')");
+    assertNull(result.getEntityContainer().getName());
+    assertEquals("Employees", result.getTargetEntitySet().getName());
+    assertEquals(UriType.URI2, result.getUriType());
+
+    assertEquals(1, result.getKeyPredicates().size());
+    assertEquals("1", result.getKeyPredicates().get(0).getLiteral());
+    assertEquals("EmployeeId", result.getKeyPredicates().get(0).getProperty().getName());
+  }
+
+  @Test
+  public void parseEmployeesEntityWithExplicitKeyAndComma() throws Exception {
+    UriInfoImpl result = parse("/Employees(EmployeeId='1,2')");
+    assertNull(result.getEntityContainer().getName());
+    assertEquals("Employees", result.getTargetEntitySet().getName());
+    assertEquals(UriType.URI2, result.getUriType());
+
+    assertEquals(1, result.getKeyPredicates().size());
+    assertEquals("1,2", result.getKeyPredicates().get(0).getLiteral());
+    assertEquals("EmployeeId", result.getKeyPredicates().get(0).getProperty().getName());
+  }
+
+  @Test
+  public void parseEmployeesEntityWithExplicitKeyAndSquoteInString() throws Exception {
+    UriInfoImpl result = parse("/Employees(EmployeeId='1''2')");
+    assertNull(result.getEntityContainer().getName());
+    assertEquals("Employees", result.getTargetEntitySet().getName());
+    assertEquals(UriType.URI2, result.getUriType());
+
+    assertEquals(1, result.getKeyPredicates().size());
+    assertEquals("1'2", result.getKeyPredicates().get(0).getLiteral());
+    assertEquals("EmployeeId", result.getKeyPredicates().get(0).getProperty().getName());
+  }
+
+  @Test
+  public void parseEmployeesEntityWithKeyValue() throws Exception {
+    UriInfoImpl result = parse("/Employees('1')/$value");
+    assertEquals("Employees", result.getTargetEntitySet().getName());
+    assertTrue(result.getStartEntitySet().getEntityType().hasStream());
+    assertEquals(UriType.URI17, result.getUriType());
+    assertTrue(result.isValue());
+
+    assertEquals(1, result.getKeyPredicates().size());
+    assertEquals("1", result.getKeyPredicates().get(0).getLiteral());
+    assertEquals("EmployeeId", result.getKeyPredicates().get(0).getProperty().getName());
+  }
+
+  @Test
+  public void parseEmployeesEntityWithKeyCount() throws Exception {
+    UriInfoImpl result = parse("/Employees('1')/$count");
+    assertEquals("Employees", result.getTargetEntitySet().getName());
+    assertEquals(UriType.URI16, result.getUriType());
+    assertTrue(result.isCount());
+
+    assertEquals(1, result.getKeyPredicates().size());
+    assertEquals("1", result.getKeyPredicates().get(0).getLiteral());
+    assertEquals("EmployeeId", result.getKeyPredicates().get(0).getProperty().getName());
+  }
+  
+  @Test
+  public void parseEmployeesEntityWithKeyCountEncoded() throws Exception {
+    UriInfoImpl result = parse("/Employees('1')/%24count");
+    assertEquals("Employees", result.getTargetEntitySet().getName());
+    assertEquals(UriType.URI16, result.getUriType());
+    assertTrue(result.isCount());
+
+    assertEquals(1, result.getKeyPredicates().size());
+    assertEquals("1", result.getKeyPredicates().get(0).getLiteral());
+    assertEquals("EmployeeId", result.getKeyPredicates().get(0).getProperty().getName());
+  }
+  
+  @Test
+  public void parseEmployeesSimpleProperty() throws Exception {
+    UriInfoImpl result = parse("/Employees('1')/EmployeeName");
+    assertNull(result.getEntityContainer().getName());
+    assertEquals("Employees", result.getTargetEntitySet().getName());
+    assertEquals(UriType.URI5, result.getUriType());
+    assertEquals("EmployeeName", result.getPropertyPath().get(0).getName());
+  }
+
+  @Test
+  public void parseEmployeesSimplePropertyValue() throws Exception {
+    UriInfoImpl result = parse("/Employees('1')/EmployeeName/$value");
+    assertNull(result.getEntityContainer().getName());
+    assertEquals("Employees", result.getTargetEntitySet().getName());
+    assertEquals(UriType.URI5, result.getUriType());
+    assertEquals("EmployeeName", result.getPropertyPath().get(0).getName());
+    assertTrue(result.isValue());
+  }
+  
+  @Test
+  public void parseEmployeesSimplePropertyValueEncoded() throws Exception {
+    UriInfoImpl result = parse("/Employees('1')/EmployeeName/%24value");
+    assertNull(result.getEntityContainer().getName());
+    assertEquals("Employees", result.getTargetEntitySet().getName());
+    assertEquals(UriType.URI5, result.getUriType());
+    assertEquals("EmployeeName", result.getPropertyPath().get(0).getName());
+    assertTrue(result.isValue());
+  }
+  
+  @Test
+  public void parseEmployeesComplexProperty() throws Exception {
+    UriInfoImpl result = parse("/Employees('1')/Location");
+    assertNull(result.getEntityContainer().getName());
+    assertEquals("Employees", result.getTargetEntitySet().getName());
+    assertEquals(UriType.URI3, result.getUriType());
+    assertEquals("Location", result.getPropertyPath().get(0).getName());
+  }
+
+  @Test
+  public void parseEmployeesComplexPropertyWithEntity() throws Exception {
+    UriInfoImpl result = parse("/Employees('1')/Location/Country");
+    assertNull(result.getEntityContainer().getName());
+    assertEquals("Employees", result.getTargetEntitySet().getName());
+    assertEquals(UriType.URI4, result.getUriType());
+    assertEquals("Location", result.getPropertyPath().get(0).getName());
+    assertEquals("Country", result.getPropertyPath().get(1).getName());
+  }
+
+  @Test
+  public void parseEmployeesComplexPropertyWithEntityValue() throws Exception {
+    UriInfoImpl result = parse("/Employees('1')/Location/Country/$value");
+    assertNull(result.getEntityContainer().getName());
+    assertEquals("Employees", result.getTargetEntitySet().getName());
+    assertEquals(UriType.URI4, result.getUriType());
+    assertEquals("Location", result.getPropertyPath().get(0).getName());
+    assertEquals("Country", result.getPropertyPath().get(1).getName());
+    assertTrue(result.isValue());
+  }
+
+  @Test
+  public void simplePropertyWrong() throws Exception {
+    parseWrongUri("/Employees('1')/EmployeeName(1)", UriSyntaxException.INVALIDSEGMENT);
+    parseWrongUri("/Employees('1')/EmployeeName()", UriSyntaxException.INVALIDSEGMENT);
+    parseWrongUri("/Employees('1')/EmployeeName/something", UriSyntaxException.INVALIDSEGMENT);
+    parseWrongUri("/Employees('1')/EmployeeName/$value/something", UriSyntaxException.MUSTBELASTSEGMENT);
+  }
+
+  @Test
+  public void complexPropertyWrong() throws Exception {
+    parseWrongUri("/Employees('1')/Location(1)", UriSyntaxException.INVALIDSEGMENT);
+    parseWrongUri("/Employees('1')/Location/somethingwrong", UriNotMatchingException.PROPERTYNOTFOUND);
+  }
+
+  @Test
+  public void EmployeesNoProperty() throws Exception {
+    parseWrongUri("/Employees('1')/somethingwrong", UriNotMatchingException.PROPERTYNOTFOUND);
+  }
+
+  @Test
+  public void parseNavigationPropertyWithEntityResult() throws Exception {
+    UriInfoImpl result = parse("/Employees('1')/ne_Manager");
+    assertEquals("Managers", result.getTargetEntitySet().getName());
+    assertEquals(UriType.URI6A, result.getUriType());
+  }
+
+  @Test
+  public void parseNavigationPropertyWithEntitySetResult() throws Exception {
+    UriInfoImpl result = parse("/Managers('1')/nm_Employees");
+    assertEquals("Employees", result.getTargetEntitySet().getName());
+    assertEquals(UriType.URI6B, result.getUriType());
+  }
+
+  @Test
+  public void parseNavigationPropertyWithEntitySetResultParenthesis() throws Exception {
+    UriInfoImpl result = parse("/Managers('1')/nm_Employees()");
+    assertEquals("Employees", result.getTargetEntitySet().getName());
+    assertEquals(UriType.URI6B, result.getUriType());
+  }
+
+  @Test
+  public void parseNavigationPropertyWithEntityResultWithKey() throws Exception {
+    UriInfoImpl result = parse("/Managers('1')/nm_Employees('1')");
+    assertEquals("Employees", result.getTargetEntitySet().getName());
+    assertEquals(UriType.URI6A, result.getUriType());
+  }
+
+  @Test
+  public void parseNavigationPropertyWithLinksOne() throws Exception {
+    UriInfoImpl result = parse("/Employees('1')/$links/ne_Manager");
+    assertEquals("Managers", result.getTargetEntitySet().getName());
+    assertTrue(result.isLinks());
+    assertEquals(UriType.URI7A, result.getUriType());
+  }
+
+  @Test
+  public void parseNavigationPropertyWithLinksMany() throws Exception {
+    UriInfoImpl result = parse("/Managers('1')/$links/nm_Employees");
+    assertEquals("Employees", result.getTargetEntitySet().getName());
+    assertTrue(result.isLinks());
+    assertEquals(UriType.URI7B, result.getUriType());
+  }
+  
+  @Test
+  public void parseNavigationPropertyWithLinksManyEncoded() throws Exception {
+    UriInfoImpl result = parse("/Managers('1')/%24links/nm_Employees");
+    assertEquals("Employees", result.getTargetEntitySet().getName());
+    assertTrue(result.isLinks());
+    assertEquals(UriType.URI7B, result.getUriType());
+  }
+  
+  @Test
+  public void parseNavigationPropertyWithManagersCount() throws Exception {
+    UriInfoImpl result = parse("/Employees('1')/ne_Manager/$count");
+    assertEquals("Managers", result.getTargetEntitySet().getName());
+    assertTrue(result.isCount());
+    assertEquals(UriType.URI16, result.getUriType());
+  }
+
+  @Test
+  public void parseNavigationPropertyWithEmployeesCount() throws Exception {
+    UriInfoImpl result = parse("/Managers('1')/nm_Employees/$count");
+    assertEquals("Employees", result.getTargetEntitySet().getName());
+    assertTrue(result.isCount());
+    assertEquals(UriType.URI15, result.getUriType());
+  }
+
+  @Test
+  public void parseNavigationPropertyWithEmployeeCount() throws Exception {
+    UriInfoImpl result = parse("Managers('1')/nm_Employees('1')/$count");
+    assertEquals("Employees", result.getTargetEntitySet().getName());
+    assertTrue(result.isCount());
+    assertEquals(UriType.URI16, result.getUriType());
+  }
+
+  @Test
+  public void parseNavigationPropertyWithLinksCountMany() throws Exception {
+    UriInfoImpl result = parse("/Managers('1')/$links/nm_Employees/$count");
+    assertEquals("Employees", result.getTargetEntitySet().getName());
+    assertTrue(result.isLinks());
+    assertTrue(result.isCount());
+    assertEquals(UriType.URI50B, result.getUriType());
+  }
+
+  @Test
+  public void parseNavigationPropertyWithLinksCountOne() throws Exception {
+    UriInfoImpl result = parse("/Employees('1')/$links/ne_Manager/$count");
+    assertEquals("Managers", result.getTargetEntitySet().getName());
+    assertTrue(result.isLinks());
+    assertTrue(result.isCount());
+    assertEquals(UriType.URI50A, result.getUriType());
+
+    result = parse("/Managers('1')/$links/nm_Employees('1')/$count");
+    assertEquals("Employees", result.getTargetEntitySet().getName());
+    assertTrue(result.isLinks());
+    assertTrue(result.isCount());
+    assertEquals(UriType.URI50A, result.getUriType());
+  }
+
+  @Test
+  public void navigationPropertyWrong() throws Exception {
+    parseWrongUri("Employees('1')/somethingwrong", UriNotMatchingException.PROPERTYNOTFOUND);
+    parseWrongUri("Employees('1')//ne_Manager", UriSyntaxException.EMPTYSEGMENT);
+    parseWrongUri("Employees('1')/ne_Manager()", UriSyntaxException.INVALIDSEGMENT);
+    parseWrongUri("Employees('1')/ne_Manager('1')", UriSyntaxException.INVALIDSEGMENT);
+    parseWrongUri("Employees('1')/$links", UriSyntaxException.MUSTNOTBELASTSEGMENT);
+    parseWrongUri("Employees('1')/$links/ne_Manager('1')", UriSyntaxException.INVALIDSEGMENT);
+    parseWrongUri("Employees('1')/$links/ne_Manager()", UriSyntaxException.INVALIDSEGMENT);
+    parseWrongUri("Employees('1')/$links/ne_Manager/somethingwrong", UriSyntaxException.INVALIDSEGMENT);
+    parseWrongUri("Employees('1')/ne_Manager/$count/somethingwrong", UriSyntaxException.MUSTBELASTSEGMENT);
+    parseWrongUri("Employees('1')/$links/ne_Manager/$count/somethingwrong", UriSyntaxException.MUSTBELASTSEGMENT);
+    parseWrongUri("Employees('1')/ne_Manager/$value", UriSyntaxException.NOMEDIARESOURCE);
+    parseWrongUri("Managers('1')/nm_Employees('1')/$value/somethingwrong", UriSyntaxException.MUSTBELASTSEGMENT);
+    parseWrongUri("Managers('1')/nm_Employees/$links", UriSyntaxException.INVALIDSEGMENT);
+    parseWrongUri("Managers('1')/nm_Employees/$links/Manager", UriSyntaxException.INVALIDSEGMENT);
+    parseWrongUri("Managers('1')/nm_Employees/somethingwrong", UriSyntaxException.INVALIDSEGMENT);
+    parseWrongUri("Employees('1')/$links/somethingwrong", UriNotMatchingException.PROPERTYNOTFOUND);
+    parseWrongUri("Employees('1')/$links/EmployeeName", UriSyntaxException.NONAVIGATIONPROPERTY);
+    parseWrongUri("Employees('1')/$links/$links/ne_Manager", UriNotMatchingException.PROPERTYNOTFOUND);
+  }
+
+  @Test
+  public void navigationPathWrongMatch() throws Exception {
+    parseWrongUri("/Employees('1')/(somethingwrong(", UriNotMatchingException.MATCHPROBLEM);
+  }
+
+  @Test
+  public void navigationSegmentWrongMatch() throws Exception {
+    parseWrongUri("/Employees('1')/$links/(somethingwrong(", UriNotMatchingException.MATCHPROBLEM);
+  }
+
+  @Test
+  public void parseTeamsEntityWithIntKeyValue() throws Exception {
+    parseWrongUri("/Teams(1)/$value", UriSyntaxException.INCOMPATIBLELITERAL);
+  }
+
+  @Test
+  public void parseWrongKey() throws Exception {
+    parseWrongUri("Employees(EmployeeId=)", UriSyntaxException.INVALIDKEYPREDICATE);
+    parseWrongUri("Employees(,)", UriSyntaxException.INVALIDKEYPREDICATE);
+    parseWrongUri("Employees(')", UriSyntaxException.UNKNOWNLITERAL);
+    parseWrongUri("Employees(0)", UriSyntaxException.INCOMPATIBLELITERAL);
+    parseWrongUri("Employees(,'1')", UriSyntaxException.INVALIDKEYPREDICATE);
+    parseWrongUri("Employees('1',)", UriSyntaxException.INVALIDKEYPREDICATE);
+    parseWrongUri("Employees('1','2')", UriSyntaxException.DUPLICATEKEYNAMES);
+    parseWrongUri("Employees(EmployeeName='1')", UriSyntaxException.INVALIDKEYPREDICATE);
+    parseWrongUri("Employees(EmployeeId='1',EmployeeId='1')", UriSyntaxException.DUPLICATEKEYNAMES);
+    parseWrongUri("/Employees(EmployeeId='1',somethingwrong=abc)", UriSyntaxException.INVALIDKEYPREDICATE);
+    parseWrongUri("/Employees(somethingwrong=1)", UriSyntaxException.INVALIDKEYPREDICATE);
+    parseWrongUri("/Container2.Photos(Id=1,,Type='abc')", UriSyntaxException.INVALIDKEYPREDICATE);
+    parseWrongUri("/Container2.Photos(Id=1;Type='abc')", UriSyntaxException.INVALIDKEYPREDICATE);
+    parseWrongUri("Container2.Photos(Id=1,'abc')", UriSyntaxException.MISSINGKEYPREDICATENAME);
+    parseWrongUri("Container2.Photos(Id=1)", UriSyntaxException.INVALIDKEYPREDICATE);
+  }
+
+  @Test
+  public void parsePhotoEntityWithExplicitKeySet() throws Exception {
+    UriInfoImpl result = parse("/Container2.Photos(Id=1,Type='abc')");
+    assertEquals("Container2", result.getEntityContainer().getName());
+    assertEquals("Photos", result.getTargetEntitySet().getName());
+    assertEquals(UriType.URI2, result.getUriType());
+    assertEquals(2, result.getKeyPredicates().size());
+    assertEquals("1", result.getKeyPredicates().get(0).getLiteral());
+    assertEquals("Id", result.getKeyPredicates().get(0).getProperty().getName());
+    assertEquals("abc", result.getKeyPredicates().get(1).getLiteral());
+    assertEquals("Type", result.getKeyPredicates().get(1).getProperty().getName());
+
+    result = parse("/Container2.Photos(Id=1,Type='abc%20xyz')");
+    assertEquals("abc xyz", result.getKeyPredicates().get(1).getLiteral());
+
+    result = parse("/Container2.Photos(Id=1,Type='image%2Fpng')");
+    assertEquals("image/png", result.getKeyPredicates().get(1).getLiteral());
+
+    result = parse("/Container2.Photos(Id=5,Type='test%2Ccomma')");
+    assertEquals("test,comma", result.getKeyPredicates().get(1).getLiteral());
+  }
+
+  @Test
+  public void parseContainerEmployeesEntitySet() throws Exception {
+    UriInfoImpl result = parse("/Container1.Employees");
+    assertEquals("Container1", result.getEntityContainer().getName());
+    assertEquals("Employees", result.getTargetEntitySet().getName());
+    assertEquals(UriType.URI1, result.getUriType());
+  }
+
+  @Test
+  public void parseContainerEmployeesEntitySetParentheses() throws Exception {
+    UriInfoImpl result = parse("/Container1.Employees()");
+    assertEquals("Container1", result.getEntityContainer().getName());
+    assertEquals("Employees", result.getTargetEntitySet().getName());
+    assertEquals(UriType.URI1, result.getUriType());
+  }
+
+  @Test
+  public void parseContainerEmployeesEntityWithKey() throws Exception {
+    UriInfoImpl result = parse("/Container1.Employees('1')");
+    assertEquals("Container1", result.getEntityContainer().getName());
+    assertEquals("Employees", result.getTargetEntitySet().getName());
+    assertEquals(UriType.URI2, result.getUriType());
+
+    assertEquals(1, result.getKeyPredicates().size());
+    assertEquals("1", result.getKeyPredicates().get(0).getLiteral());
+    assertEquals("EmployeeId", result.getKeyPredicates().get(0).getProperty().getName());
+  }
+
+  @Test
+  public void parseNonexistentContainer() throws Exception {
+    parseWrongUri("/somethingwrong.Employees()", UriNotMatchingException.CONTAINERNOTFOUND);
+  }
+
+  @Test
+  public void parseInvalidSegment() throws Exception {
+    parseWrongUri("/.somethingwrong", UriNotMatchingException.MATCHPROBLEM);
+  }
+
+  @Test
+  public void parseFunctionImports() throws Exception {
+    UriInfoImpl result = parse("EmployeeSearch");
+    assertEquals("EmployeeSearch", result.getFunctionImport().getName());
+    assertEquals(EdmTypeKind.ENTITY, result.getTargetType().getKind());
+    assertEquals(UriType.URI1, result.getUriType());
+
+    result = parse("AllLocations");
+    assertEquals("AllLocations", result.getFunctionImport().getName());
+    assertEquals(UriType.URI11, result.getUriType());
+
+    result = parse("AllUsedRoomIds");
+    assertEquals("AllUsedRoomIds", result.getFunctionImport().getName());
+    assertEquals(UriType.URI13, result.getUriType());
+
+    result = parse("MaximalAge");
+    assertEquals("MaximalAge", result.getFunctionImport().getName());
+    assertEquals(UriType.URI14, result.getUriType());
+
+    result = parse("MaximalAge/$value");
+    assertEquals("MaximalAge", result.getFunctionImport().getName());
+    assertTrue(result.isValue());
+    assertEquals(UriType.URI14, result.getUriType());
+    
+    result = parse("MaximalAge/%24value");
+    assertEquals("MaximalAge", result.getFunctionImport().getName());
+    assertTrue(result.isValue());
+    assertEquals(UriType.URI14, result.getUriType());
+    
+    result = parse("MostCommonLocation");
+    assertEquals("MostCommonLocation", result.getFunctionImport().getName());
+    assertEquals(UriType.URI12, result.getUriType());
+
+    result = parse("ManagerPhoto?Id='1'");
+    assertEquals("ManagerPhoto", result.getFunctionImport().getName());
+    assertEquals(UriType.URI14, result.getUriType());
+
+    result = parse("OldestEmployee");
+    assertEquals("OldestEmployee", result.getFunctionImport().getName());
+    assertEquals(UriType.URI10, result.getUriType());
+  }
+
+  @Test
+  public void parseFunctionImportParameters() throws Exception {
+    UriInfoImpl result = parse("EmployeeSearch?q='Hugo'&notaparameter=2");
+    assertEquals("EmployeeSearch", result.getFunctionImport().getName());
+    assertEquals(1, result.getFunctionImportParameters().size());
+    assertEquals(EdmSimpleTypeKind.String.getEdmSimpleTypeInstance(), result.getFunctionImportParameters().get("q")
+        .getType());
+    assertEquals("Hugo", result.getFunctionImportParameters().get("q").getLiteral());
+  }
+  
+  @Test
+  public void parseFunctionImportParametersWithFacets() throws Exception {
+    UriInfoImpl result = parse("FINullableParameter");
+    assertEquals("FINullableParameter", result.getFunctionImport().getName());
+    assertTrue(result.getFunctionImportParameters().isEmpty());
+    
+    result = parse("FINullableParameter?Id='A'");
+    assertEquals("FINullableParameter", result.getFunctionImport().getName());
+    assertFalse(result.getFunctionImportParameters().isEmpty());
+    assertEquals("A", result.getFunctionImportParameters().get("Id").getLiteral());
+  }
+
+  @Test
+  public void parseWrongFunctionImports() throws Exception {
+    parseWrongUri("EmployeeSearch?q=42", UriSyntaxException.INCOMPATIBLELITERAL);
+    parseWrongUri("AllLocations/$value", UriSyntaxException.MUSTBELASTSEGMENT);
+    parseWrongUri("MaximalAge()", UriSyntaxException.INVALIDSEGMENT);
+    parseWrongUri("MaximalAge/somethingwrong", UriSyntaxException.INVALIDSEGMENT);
+    parseWrongUri("ManagerPhoto", UriSyntaxException.MISSINGPARAMETER);
+    parseWrongUri("ManagerPhoto?Id='", UriSyntaxException.UNKNOWNLITERAL);
+  }
+
+  @Test
+  public void parseWrongFunctionImportParameters() throws Exception {
+    // override parameter type for testing literal parsing errors
+    when(edm.getDefaultEntityContainer().getFunctionImport("ManagerPhoto").getParameter("Id").getType())
+        .thenReturn(EdmSimpleTypeKind.Binary.getEdmSimpleTypeInstance());
+    parseWrongUri("ManagerPhoto?Id=X'Z'", UriSyntaxException.LITERALFORMAT);
+    when(edm.getDefaultEntityContainer().getFunctionImport("ManagerPhoto").getParameter("Id").getType())
+        .thenReturn(EdmSimpleTypeKind.Int32.getEdmSimpleTypeInstance());
+    parseWrongUri("ManagerPhoto?Id=12345678901234567890", UriSyntaxException.LITERALFORMAT);
+  }
+
+  @Test
+  public void parseSystemQueryOptions() throws Exception {
+    UriInfoImpl result = parse("Employees?$format=json&$inlinecount=allpages&$skiptoken=abc&$skip=2&$top=1");
+    assertEquals("Employees", result.getTargetEntitySet().getName());
+    assertEquals(UriType.URI1, result.getUriType());
+    assertEquals("json", result.getFormat());
+    assertEquals(InlineCount.ALLPAGES, result.getInlineCount());
+    assertEquals("abc", result.getSkipToken());
+    assertEquals(2, result.getSkip().intValue());
+    assertEquals(1, result.getTop().intValue());
+    
+    result = parse("Employees?$format=json&%24inlinecount=allpages&%24skiptoken=abc&%24skip=2&$top=1");
+    assertEquals("Employees", result.getTargetEntitySet().getName());
+    assertEquals(UriType.URI1, result.getUriType());
+    assertEquals("json", result.getFormat());
+    assertEquals(InlineCount.ALLPAGES, result.getInlineCount());
+    assertEquals("abc", result.getSkipToken());
+    assertEquals(2, result.getSkip().intValue());
+    assertEquals(1, result.getTop().intValue());
+    
+    result = parse("Employees?$format=atom&$inlinecount=none&$skip=0&$top=0");
+    assertEquals("Employees", result.getTargetEntitySet().getName());
+    assertEquals(UriType.URI1, result.getUriType());
+    assertEquals("atom", result.getFormat());
+    assertEquals(InlineCount.NONE, result.getInlineCount());
+    assertEquals(0, result.getSkip().intValue());
+    assertEquals(0, result.getTop().intValue());
+
+    result = parse("Employees?$format=json&$inlinecount=none");
+    assertEquals("Employees", result.getTargetEntitySet().getName());
+    assertEquals(UriType.URI1, result.getUriType());
+    assertEquals("json", result.getFormat());
+    assertEquals(InlineCount.NONE, result.getInlineCount());
+    assertNull(result.getSkip());
+    assertNull(result.getTop());
+
+    result = parse("Employees?$format=atom");
+    assertEquals("Employees", result.getTargetEntitySet().getName());
+    assertEquals(UriType.URI1, result.getUriType());
+    assertEquals("atom", result.getFormat());
+
+    result = parse("Employees?$format=xml");
+    assertEquals("Employees", result.getTargetEntitySet().getName());
+    assertEquals(UriType.URI1, result.getUriType());
+    assertEquals("xml", result.getFormat());
+    assertNull(result.getTop());
+
+    result = parse("Employees?$format=custom/*");
+    assertNotNull(result.getFormat());
+    assertEquals("custom/*", result.getFormat().toString());
+
+    result = parse("/Employees('1')/Location/Country?$format=json");
+    assertEquals("Employees", result.getTargetEntitySet().getName());
+    assertEquals(UriType.URI4, result.getUriType());
+    assertEquals("json", result.getFormat());
+
+    result = parse("/Employees('1')/EmployeeName?$format=json");
+    assertEquals("Employees", result.getTargetEntitySet().getName());
+    assertEquals(UriType.URI5, result.getUriType());
+    assertEquals("json", result.getFormat());
+
+    result = parse("Employees?$filter=Age%20gt%2020&$orderby=EmployeeName%20desc");
+    assertEquals("Employees", result.getTargetEntitySet().getName());
+    assertEquals(UriType.URI1, result.getUriType());
+    assertNotNull(result.getFilter());
+    assertNotNull(result.getOrderBy());
+    assertEquals("EmployeeName desc", result.getOrderBy().getUriLiteral());
+  }
+  
+  @Test(expected=UriSyntaxException.class)
+  public void parseFilterOptionsWithError1() throws Exception {       
+    ODataClient.newInstance().parseUri(edm, "Managers?count?$filter=nm_Employees/EmployeeName%20eq%20%27Archana%27");
+  }
+
+  @Test
+  public void parseWrongSystemQueryOptions() throws Exception {
+    parseWrongUri("Employees??", UriSyntaxException.URISYNTAX);
+    parseWrongUri("Employees?$inlinecount=no", UriSyntaxException.INVALIDVALUE);
+    parseWrongUri("Employees?&$skiptoken==", UriSyntaxException.INVALIDNULLVALUE);
+    parseWrongUri("Employees?$somethingwrong", UriSyntaxException.INVALIDSYSTEMQUERYOPTION);
+    parseWrongUri("Employees?$somethingwrong=", UriSyntaxException.INVALIDSYSTEMQUERYOPTION);
+    parseWrongUri("Employees?$somethingwrong=adjaodjai", UriSyntaxException.INVALIDSYSTEMQUERYOPTION);
+    parseWrongUri("Employees?$formatformat=xml", UriSyntaxException.INVALIDSYSTEMQUERYOPTION);
+    parseWrongUri("Employees?$Format=atom", UriSyntaxException.INVALIDSYSTEMQUERYOPTION);
+    parseWrongUri("Employees?$filter=Age", UriSyntaxException.INVALIDFILTEREXPRESSION);
+    parseWrongUri("Employees?$filter=(Age", UriSyntaxException.INVALIDFILTEREXPRESSION);
+    parseWrongUri("Employees?$orderby=desc", UriSyntaxException.INVALIDORDERBYEXPRESSION);
+  }
+
+  @Test
+  public void parseWrongRedundantSystemQueryOptions() throws Exception {
+    parseWrongUri("Employees?$top=1&$top=2", UriSyntaxException.DUPLICATESYSTEMQUERYPARAMETES);
+    parseWrongUri("Employees?$top=1&$skip=1&$top=2", UriSyntaxException.DUPLICATESYSTEMQUERYPARAMETES);
+    parseWrongUri("Employees?$top=1&$top=1", UriSyntaxException.DUPLICATESYSTEMQUERYPARAMETES);
+    parseWrongUri("Employees?$skip=1&$skip=2", UriSyntaxException.DUPLICATESYSTEMQUERYPARAMETES);
+    parseWrongUri("Employees?$expand=ne_Manager&$expand=ne_Manager", UriSyntaxException.DUPLICATESYSTEMQUERYPARAMETES);
+    parseWrongUri("Employees?$orderby=Name%20desc&$orderby=Birthday%20desc",
+        UriSyntaxException.DUPLICATESYSTEMQUERYPARAMETES);
+    parseWrongUri("Employees?$select=EmployeeName&$select=EmployeeName",
+        UriSyntaxException.DUPLICATESYSTEMQUERYPARAMETES);
+    parseWrongUri("Employees?$filter=EmployeeName%20eq%20'Foo'&$filter=EmployeeName%20ne%20'Bar'",
+        UriSyntaxException.DUPLICATESYSTEMQUERYPARAMETES);
+    parseWrongUri("Employees?$inlinecount=allpages&$inlinecount=none",
+        UriSyntaxException.DUPLICATESYSTEMQUERYPARAMETES);
+    parseWrongUri("Employees?$format=xml&$format=json", UriSyntaxException.DUPLICATESYSTEMQUERYPARAMETES);
+  }
+
+  @Test
+  public void parseWrongSystemQueryOptionSkip() throws Exception {
+    parseWrongUri("Employees?$skip=-1", UriSyntaxException.INVALIDNEGATIVEVALUE);
+    parseWrongUri("Employees?$skip=-0", UriSyntaxException.INVALIDNEGATIVEVALUE);
+    parseWrongUri("Employees?$skip=+1", UriSyntaxException.INVALIDVALUE);
+    parseWrongUri("Employees?$skip=+0", UriSyntaxException.INVALIDVALUE);
+    parseWrongUri("Employees?$skip=a", UriSyntaxException.INVALIDVALUE);
+    parseWrongUri("Employees?$skip=-a", UriSyntaxException.INVALIDVALUE);
+    parseWrongUri("Employees?$skip=+a", UriSyntaxException.INVALIDVALUE);
+    parseWrongUri("Employees?$skip='a'", UriSyntaxException.INVALIDVALUE);
+    parseWrongUri("Employees?$skip=-'a'", UriSyntaxException.INVALIDVALUE);
+    parseWrongUri("Employees?$skip=+'a'", UriSyntaxException.INVALIDVALUE);
+    parseWrongUri("Employees?$skip=-'a'", UriSyntaxException.INVALIDVALUE);
+    parseWrongUri("Employees?$skip='+a'", UriSyntaxException.INVALIDVALUE);
+    parseWrongUri("Employees?$skip='-a'", UriSyntaxException.INVALIDVALUE);
+    parseWrongUri("Employees?$skip=12345678901234567890", UriSyntaxException.INVALIDVALUE);
+  }
+
+  @Test
+  public void parseWrongSystemQueryOptionTop() throws Exception {
+    parseWrongUri("Employees?$top=-1", UriSyntaxException.INVALIDNEGATIVEVALUE);
+    parseWrongUri("Employees?$top=-0", UriSyntaxException.INVALIDNEGATIVEVALUE);
+    parseWrongUri("Employees?$top=+1", UriSyntaxException.INVALIDVALUE);
+    parseWrongUri("Employees?$top=+0", UriSyntaxException.INVALIDVALUE);
+    parseWrongUri("Employees?$top=a", UriSyntaxException.INVALIDVALUE);
+    parseWrongUri("Employees?$top=-a", UriSyntaxException.INVALIDVALUE);
+    parseWrongUri("Employees?$top=+a", UriSyntaxException.INVALIDVALUE);
+    parseWrongUri("Employees?$top='a'", UriSyntaxException.INVALIDVALUE);
+    parseWrongUri("Employees?$top=-'a'", UriSyntaxException.INVALIDVALUE);
+    parseWrongUri("Employees?$top=+'a'", UriSyntaxException.INVALIDVALUE);
+    parseWrongUri("Employees?$top=12345678901234567890", UriSyntaxException.INVALIDVALUE);
+  }
+
+  @Test
+  public void parseWrongSystemQueryOptionInitialValues() throws Exception {
+    parseWrongUri("Employees?$expand=", UriSyntaxException.INVALIDNULLVALUE);
+    parseWrongUri("Employees?$filter=", UriSyntaxException.INVALIDNULLVALUE);
+    parseWrongUri("Employees?$orderby=", UriSyntaxException.INVALIDNULLVALUE);
+    parseWrongUri("Employees?$format=", UriSyntaxException.INVALIDNULLVALUE);
+    parseWrongUri("Employees?$skip=", UriSyntaxException.INVALIDNULLVALUE);
+    parseWrongUri("Employees?$top=", UriSyntaxException.INVALIDNULLVALUE);
+    parseWrongUri("Employees?$skiptoken=", UriSyntaxException.INVALIDNULLVALUE);
+    parseWrongUri("Employees?$inlinecount=", UriSyntaxException.INVALIDNULLVALUE);
+    parseWrongUri("Employees?$select=", UriSyntaxException.INVALIDNULLVALUE);
+
+    parseWrongUri("Employees?$expand", UriSyntaxException.INVALIDNULLVALUE);
+    parseWrongUri("Employees?$filter", UriSyntaxException.INVALIDNULLVALUE);
+    parseWrongUri("Employees?$orderby", UriSyntaxException.INVALIDNULLVALUE);
+    parseWrongUri("Employees?$format", UriSyntaxException.INVALIDNULLVALUE);
+    parseWrongUri("Employees?$skip", UriSyntaxException.INVALIDNULLVALUE);
+    parseWrongUri("Employees?$top", UriSyntaxException.INVALIDNULLVALUE);
+    parseWrongUri("Employees?$skiptoken", UriSyntaxException.INVALIDNULLVALUE);
+    parseWrongUri("Employees?$inlinecount", UriSyntaxException.INVALIDNULLVALUE);
+    parseWrongUri("Employees?$select", UriSyntaxException.INVALIDNULLVALUE);
+  }
+
+  @Test
+  public void parseCompatibleSystemQueryOptions() throws Exception {
+    UriInfoImpl result = parse("Employees?$format=json&$inlinecount=allpages&$skiptoken=abc&$skip=2&$top=1");
+    assertEquals("Employees", result.getStartEntitySet().getName());
+    assertEquals(UriType.URI1, result.getUriType());
+    assertEquals("json", result.getFormat());
+    assertEquals(InlineCount.ALLPAGES, result.getInlineCount());
+    assertEquals("abc", result.getSkipToken());
+    assertEquals(2, result.getSkip().intValue());
+    assertEquals(1, result.getTop().intValue());
+  }
+
+  @Test
+  public void parseInCompatibleSystemQueryOptions() throws Exception {
+    parseWrongUri("$metadata?$top=1", UriSyntaxException.INCOMPATIBLESYSTEMQUERYOPTION);
+    parseWrongUri("Employees('1')?$format=json&$inlinecount=allpages&$skiptoken=abc&$skip=2&$top=1",
+        UriSyntaxException.INCOMPATIBLESYSTEMQUERYOPTION);
+    parseWrongUri("/Employees('1')/Location/Country/$value?$format=json",
+        UriSyntaxException.INCOMPATIBLESYSTEMQUERYOPTION);
+    parseWrongUri("/Employees('1')/Location/Country/$value?$skip=2", UriSyntaxException.INCOMPATIBLESYSTEMQUERYOPTION);
+    parseWrongUri("/Employees('1')/EmployeeName/$value?$format=json", UriSyntaxException.INCOMPATIBLESYSTEMQUERYOPTION);
+    parseWrongUri("/Employees('1')/EmployeeName/$value?$skip=2", UriSyntaxException.INCOMPATIBLESYSTEMQUERYOPTION);
+  }
+
+  @Test
+  public void parsePossibleQueryOptions() throws Exception {
+    UriInfoImpl result = parse("EmployeeSearch?q='a'&client=100&odata-debug=true");
+    assertEquals(2, result.getCustomQueryOptions().size());
+    assertEquals("100", result.getCustomQueryOptions().get("client"));
+    assertEquals("true", result.getCustomQueryOptions().get("odata-debug"));
+  }
+
+  @Test
+  public void parseSystemQueryOptionSelectSingle() throws Exception {
+    UriInfoImpl result = parse("Employees?$select=EmployeeName");
+    assertEquals("Employees", result.getTargetEntitySet().getName());
+    assertEquals(UriType.URI1, result.getUriType());
+    assertEquals(1, result.getSelect().size());
+    assertEquals("EmployeeName", result.getSelect().get(0).getProperty().getName());
+    
+    result = parse("Employees?%24select=EmployeeName");
+    assertEquals("Employees", result.getTargetEntitySet().getName());
+    assertEquals(UriType.URI1, result.getUriType());
+    assertEquals(1, result.getSelect().size());
+    assertEquals("EmployeeName", result.getSelect().get(0).getProperty().getName());
+    
+    result = parse("Employees?$select=*");
+    assertEquals("Employees", result.getTargetEntitySet().getName());
+    assertEquals(UriType.URI1, result.getUriType());
+    assertEquals(1, result.getSelect().size());
+    assertTrue(result.getSelect().get(0).isStar());
+
+    result = parse("Employees?$select=Location");
+    assertEquals("Employees", result.getTargetEntitySet().getName());
+    assertEquals(UriType.URI1, result.getUriType());
+    assertEquals(1, result.getSelect().size());
+    assertEquals("Location", result.getSelect().get(0).getProperty().getName());
+
+    result = parse("Employees?$select=ne_Manager");
+    assertEquals("Employees", result.getTargetEntitySet().getName());
+    assertEquals(UriType.URI1, result.getUriType());
+    assertEquals(1, result.getSelect().size());
+    assertEquals(1, result.getSelect().get(0).getNavigationPropertySegments().size());
+    assertEquals("Managers", result.getSelect().get(0).getNavigationPropertySegments().get(0).getTargetEntitySet()
+        .getName());
+    assertNull(result.getSelect().get(0).getProperty());
+
+    result = parse("Teams?$select=nt_Employees/ne_Manager/*");
+    assertEquals(1, result.getSelect().size());
+    assertEquals(2, result.getSelect().get(0).getNavigationPropertySegments().size());
+    assertNull(result.getSelect().get(0).getProperty());
+    assertTrue(result.getSelect().get(0).isStar());
+  }
+
+  @Test
+  public void parseSystemQueryOptionSelectMultiple() throws Exception {
+    UriInfoImpl result = parse("Employees?$select=EmployeeName,Location");
+    assertEquals("Employees", result.getTargetEntitySet().getName());
+    assertEquals(UriType.URI1, result.getUriType());
+    assertEquals(2, result.getSelect().size());
+    assertEquals("EmployeeName", result.getSelect().get(0).getProperty().getName());
+    assertEquals("Location", result.getSelect().get(1).getProperty().getName());
+
+    result = parse("Employees?$select=%20ne_Manager,%20EmployeeName,%20Location");
+    assertEquals("Employees", result.getTargetEntitySet().getName());
+    assertEquals(UriType.URI1, result.getUriType());
+    assertEquals(3, result.getSelect().size());
+    assertEquals("EmployeeName", result.getSelect().get(1).getProperty().getName());
+    assertEquals("Location", result.getSelect().get(2).getProperty().getName());
+    assertEquals(1, result.getSelect().get(0).getNavigationPropertySegments().size());
+    assertEquals("Managers", result.getSelect().get(0).getNavigationPropertySegments().get(0).getTargetEntitySet()
+        .getName());
+
+    result = parse("Managers('1')?$select=nm_Employees/EmployeeName,nm_Employees/Location");
+    assertEquals("Managers", result.getTargetEntitySet().getName());
+    assertEquals(UriType.URI2, result.getUriType());
+    assertEquals(2, result.getSelect().size());
+    assertEquals("EmployeeName", result.getSelect().get(0).getProperty().getName());
+    assertEquals("Location", result.getSelect().get(1).getProperty().getName());
+    assertEquals(1, result.getSelect().get(0).getNavigationPropertySegments().size());
+    assertEquals("Employees",
+        result.getSelect().get(0).getNavigationPropertySegments().get(0).getTargetEntitySet().getName());
+  }
+
+  @Test
+  public void parseSystemQueryOptionSelectNegative() throws Exception {
+    parseWrongUri("Employees?$select=somethingwrong", UriNotMatchingException.PROPERTYNOTFOUND);
+    parseWrongUri("Employees?$select=*/Somethingwrong", UriSyntaxException.INVALIDSEGMENT);
+    parseWrongUri("Employees?$select=EmployeeName/*", UriSyntaxException.INVALIDSEGMENT);
+    parseWrongUri("Employees?$select=,EmployeeName", UriSyntaxException.EMPTYSEGMENT);
+    parseWrongUri("Employees?$select=EmployeeName,", UriSyntaxException.EMPTYSEGMENT);
+    parseWrongUri("Employees?$select=EmployeeName,,Location", UriSyntaxException.EMPTYSEGMENT);
+    parseWrongUri("Employees?$select=*EmployeeName", UriNotMatchingException.PROPERTYNOTFOUND);
+    parseWrongUri("Employees?$select=EmployeeName*", UriNotMatchingException.PROPERTYNOTFOUND);
+    parseWrongUri("Employees?$select=/EmployeeName", UriSyntaxException.EMPTYSEGMENT);
+    parseWrongUri("Employees?$select=EmployeeName/", UriSyntaxException.EMPTYSEGMENT);
+    parseWrongUri("Employees?$select=Location/City", UriSyntaxException.INVALIDSEGMENT);
+    parseWrongUri("Teams('1')?$select=nt_Employees/Id", UriNotMatchingException.PROPERTYNOTFOUND);
+    parseWrongUri("Teams('1')?$select=nt_Employees//*", UriSyntaxException.EMPTYSEGMENT);
+  }
+
+  @Test
+  public void parseSystemQueryOptionExpand() throws Exception {
+    UriInfoImpl result = parse("Managers('1')?$expand=nm_Employees");
+    assertEquals("Managers", result.getTargetEntitySet().getName());
+    assertEquals(UriType.URI2, result.getUriType());
+    assertEquals(1, result.getExpand().size());
+    assertEquals(1, result.getExpand().get(0).size());
+    assertEquals("Employees", result.getExpand().get(0).get(0).getTargetEntitySet().getName());
+    assertEquals(result.getTargetEntitySet().getEntityType().getProperty("nm_Employees"),
+        result.getExpand().get(0).get(0).getNavigationProperty());
+    
+    result = parse("Managers('1')?%24expand=nm_Employees");
+    assertEquals("Managers", result.getTargetEntitySet().getName());
+    assertEquals(UriType.URI2, result.getUriType());
+    assertEquals(1, result.getExpand().size());
+    assertEquals(1, result.getExpand().get(0).size());
+    assertEquals("Employees", result.getExpand().get(0).get(0).getTargetEntitySet().getName());
+    assertEquals(result.getTargetEntitySet().getEntityType().getProperty("nm_Employees"),
+        result.getExpand().get(0).get(0).getNavigationProperty());
+  }
+
+  @Test
+  public void parseSystemQueryOptionExpandWrong() throws Exception {
+    parseWrongUri("Managers('1')?$expand=,nm_Employees", UriSyntaxException.EMPTYSEGMENT);
+    parseWrongUri("Managers('1')?$expand=nm_Employees,", UriSyntaxException.EMPTYSEGMENT);
+    parseWrongUri("Managers('1')?$expand=nm_Employees,,", UriSyntaxException.EMPTYSEGMENT);
+    parseWrongUri("Managers('1')?$expand=nm_Employees,,nm_Employees", UriSyntaxException.EMPTYSEGMENT);
+    parseWrongUri("Managers('1')?$expand=nm_Employees, somethingwrong", UriSyntaxException.NOTEXT);
+    parseWrongUri("Managers('1')?$expand=/nm_Employees", UriSyntaxException.EMPTYSEGMENT);
+    parseWrongUri("Managers('1')?$expand=nm_Employees/", UriSyntaxException.EMPTYSEGMENT);
+    parseWrongUri("Managers('1')?$expand=nm_Employees//", UriSyntaxException.EMPTYSEGMENT);
+    parseWrongUri("Managers('1')?$expand=somethingwrong", UriNotMatchingException.PROPERTYNOTFOUND);
+    parseWrongUri("Managers('1')?$expand=nm_Employees/EmployeeName", UriSyntaxException.NONAVIGATIONPROPERTY);
+    parseWrongUri("Managers('1')?$expand=nm_Employees/Location", UriSyntaxException.NONAVIGATIONPROPERTY);
+    parseWrongUri("Managers('1')?$expand=nm_Employees/somethingwrong", UriNotMatchingException.PROPERTYNOTFOUND);
+    parseWrongUri("Managers('1')?$expand=nm_Employees/*", UriNotMatchingException.PROPERTYNOTFOUND);
+    parseWrongUri("Managers('1')?$expand=nm_Employees/*,somethingwrong", UriNotMatchingException.PROPERTYNOTFOUND);
+    parseWrongUri("Managers('1')?$expand=nm_Employees/*,some()", UriNotMatchingException.PROPERTYNOTFOUND);
+    parseWrongUri("Managers('1')?$expand=nm_Employees/(...)", UriNotMatchingException.PROPERTYNOTFOUND);
+    parseWrongUri("Teams('1')?$expand=nt_Employees//ne_Manager", UriSyntaxException.EMPTYSEGMENT);
+  }
+
+  private void wrongGetKey(final EdmEntitySet entitySet, final String link, final String serviceRoot,
+      final MessageReference exceptionContext) throws ODataException {
+    try {
+      new UriParserImpl(null).getKeyFromEntityLink(entitySet, link,
+          serviceRoot == null ? null : URI.create(serviceRoot));
+      fail("Expected UriParserException not thrown");
+    } catch (ODataMessageException e) {
+      assertNotNull(e);
+      assertEquals(exceptionContext.getKey(), e.getMessageReference().getKey());
+    }
+  }
+
+  @Test
+  public void getKeyFromLink() throws Exception {
+    final EdmEntitySet entitySet = edm.getDefaultEntityContainer().getEntitySet("Teams");
+    final EdmEntitySet entitySet2 = edm.getEntityContainer("Container2").getEntitySet("Photos");
+    final String serviceRoot = "http://service.com/example.svc/";
+    final UriParserImpl parser = new UriParserImpl(null);
+
+    List<KeyPredicate> key = parser.getKeyFromEntityLink(entitySet, "Teams('1')", null);
+    assertEquals(1, key.size());
+    assertEquals(entitySet.getEntityType().getKeyProperties().get(0), key.get(0).getProperty());
+    assertEquals("1", key.get(0).getLiteral());
+
+    key = parser.getKeyFromEntityLink(entitySet, "Teams(Id='2')", URI.create(serviceRoot));
+    assertEquals("2", key.get(0).getLiteral());
+
+    key = parser.getKeyFromEntityLink(entitySet, serviceRoot + "Teams('3')", URI.create(serviceRoot));
+    assertEquals("3", key.get(0).getLiteral());
+
+    key = parser.getKeyFromEntityLink(entitySet2, "Container2.Photos(Id=4,Type='test')", null);
+    assertEquals(2, key.size());
+
+    wrongGetKey(entitySet, "someContainer.Teams('5')", null, UriNotMatchingException.CONTAINERNOTFOUND);
+    wrongGetKey(entitySet, "Employees('6')/ne_Team", null, UriNotMatchingException.MATCHPROBLEM);
+    wrongGetKey(entitySet, "Teams()", null, UriSyntaxException.ENTITYSETINSTEADOFENTITY);
+    wrongGetKey(entitySet, "Teams('8')/Id", null, UriNotMatchingException.MATCHPROBLEM);
+    wrongGetKey(entitySet, "Rooms('9')", null, UriNotMatchingException.NOTFOUND);
+    wrongGetKey(entitySet, "anotherServiceRoot/Teams('10')", serviceRoot, UriNotMatchingException.NOTFOUND);
+    wrongGetKey(entitySet2, "Photos(Id=11,Type='test')", null, UriNotMatchingException.CONTAINERNOTFOUND);
+    wrongGetKey(entitySet2, "anotherContainer.Photos(Id=12,Type='test')", null,
+        UriNotMatchingException.CONTAINERNOTFOUND);
+  }
+
+  @Test
+  public void createPathSegment() {
+    PathSegment segment = UriParser.createPathSegment("simple", null);
+    assertEquals("simple", segment.getPath());
+    assertTrue(segment.getMatrixParameters().isEmpty());
+
+    Map<String, List<String>> matrixParameter = new HashMap<String, List<String>>();
+    matrixParameter.put("parameter1", Arrays.asList("one", "two"));
+    PathSegment segmentWithMatrix = UriParser.createPathSegment("matrix", matrixParameter);
+    assertEquals("matrix", segmentWithMatrix.getPath());
+    assertEquals(1, segmentWithMatrix.getMatrixParameters().size());
+    assertEquals(2, segmentWithMatrix.getMatrixParameters().get("parameter1").size());
+    assertTrue(segmentWithMatrix.getMatrixParameters().get("parameter1").contains("one"));
+    assertTrue(segmentWithMatrix.getMatrixParameters().get("parameter1").contains("two"));
+  }
+  
+  /**
+   * Parse the URI part after an OData service root, given as string.
+   * Query parameters can be included.
+   * @param uri the URI part
+   * @return a {@link UriInfoImpl} instance containing the parsed information
+   */
+  private UriInfoImpl parse(final String uri) throws UriSyntaxException, UriNotMatchingException, EdmException {
+    final String[] path = uri.split("\\?", -1);
+    if (path.length > 2) {
+      throw new UriSyntaxException(UriSyntaxException.URISYNTAX);
+    }
+
+    final List<PathSegment> pathSegments =
+        MockFacade.getPathSegmentsAsODataPathSegmentMock(Arrays.asList(path[0].split("/", -1)));
+    final Map<String, List<String>> queryParameters = getQueryParameters(path.length == 2 ? unescape(path[1]) : "");
+
+    return (UriInfoImpl) ODataClient.newInstance().parseUri(edm, pathSegments, queryParameters);
+  }
+  
+  private Map<String, List<String>> getQueryParameters(final String uri) {
+    Map<String, List<String>> allQueryParameters = new HashMap<String, List<String>>();
+
+    for (final String option : uri.split("&")) {
+      final String[] keyAndValue = option.split("=");
+      List<String> list = allQueryParameters.containsKey(keyAndValue[0]) ?
+          allQueryParameters.get(keyAndValue[0]) : new LinkedList<String>();
+
+      list.add(keyAndValue.length == 2 ? keyAndValue[1] : "");
+
+      allQueryParameters.put(keyAndValue[0], list);
+    }
+
+    return allQueryParameters;
+  }
+  
+  private String unescape(final String s) throws UriSyntaxException {
+    try {
+      return new URI(s).getPath();
+    } catch (URISyntaxException e) {
+      throw new UriSyntaxException(UriSyntaxException.NOTEXT);
+    }
+  }
+
+  private void parseWrongUri(final String uri, final MessageReference exceptionContext) {
+    try {
+      parse(uri);
+      fail("Expected UriParserException not thrown");
+    } catch (ODataMessageException e) {
+      assertNotNull(e);
+      assertEquals(exceptionContext.getKey(), e.getMessageReference().getKey());
+    }
+  }
+  
+  @Test
+  public void testParseUri() throws UriSyntaxException, UriNotMatchingException, EdmException {
+    UriInfo result = ODataClient.newInstance().parseUri(edm, 
+        "Employees?$filter=EmployeeName%20gt%20%27Archana%27");
+    assertEquals("Employees", result.getTargetEntitySet().getName());
+    assertNotNull(result.getFilter());
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/resources/EmployeeContentOnly.xml
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/resources/EmployeeContentOnly.xml b/odata2-lib/odata-client-core/src/test/resources/EmployeeContentOnly.xml
new file mode 100644
index 0000000..161b730
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/resources/EmployeeContentOnly.xml
@@ -0,0 +1,37 @@
+<!--
+  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.
+-->
+<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://host:8080/ReferenceScenario.svc/">
+	<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:City m:type="RefScenario.c_City">
+				<d:PostalCode>69124</d:PostalCode>
+				<d:CityName>Heidelberg</d:CityName>
+			</d:City>
+			<d:Country>Germany</d:Country>
+		</d:Location>
+		<d:Age>52</d:Age>
+		<d:EntryDate>1999-01-01T00:00:00</d:EntryDate>
+		<d:ImageUrl>Employees('1')/$value</d:ImageUrl>
+	</m:properties>
+</entry>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/resources/EmployeeContentOnlyWithNavigationLink.xml
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/resources/EmployeeContentOnlyWithNavigationLink.xml b/odata2-lib/odata-client-core/src/test/resources/EmployeeContentOnlyWithNavigationLink.xml
new file mode 100644
index 0000000..dfa1b95
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/resources/EmployeeContentOnlyWithNavigationLink.xml
@@ -0,0 +1,38 @@
+<!--
+  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.
+-->
+<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://host:8080/ReferenceScenario.svc/">
+	<link href="Managers('1')" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager" title="ne_Manager" type="application/atom+xml;type=entry"/>
+	<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:City m:type="RefScenario.c_City">
+				<d:PostalCode>69124</d:PostalCode>
+				<d:CityName>Heidelberg</d:CityName>
+			</d:City>
+			<d:Country>Germany</d:Country>
+		</d:Location>
+		<d:Age>52</d:Age>
+		<d:EntryDate>1999-01-01T00:00:00</d:EntryDate>
+		<d:ImageUrl>Employees('1')/$value</d:ImageUrl>
+	</m:properties>
+</entry>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/resources/JsonBuilding.json
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/resources/JsonBuilding.json b/odata2-lib/odata-client-core/src/test/resources/JsonBuilding.json
new file mode 100644
index 0000000..598ee8b
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/resources/JsonBuilding.json
@@ -0,0 +1,17 @@
+{
+	"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" : {
+			"__deferred" : {
+				"uri" : "http://localhost:8080/ReferenceScenario.svc/Buildings('1')/nb_Rooms"
+			}
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/resources/JsonBuildingWithInlineRooms.json
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/resources/JsonBuildingWithInlineRooms.json b/odata2-lib/odata-client-core/src/test/resources/JsonBuildingWithInlineRooms.json
new file mode 100644
index 0000000..f02ae54
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/resources/JsonBuildingWithInlineRooms.json
@@ -0,0 +1,37 @@
+{
+	"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" : {
+			"results" : [{
+					"__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"
+						}
+					}
+				}
+			]
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/resources/JsonBuildingWithInlineRoomsAndNextLinkAndCount.json
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/resources/JsonBuildingWithInlineRoomsAndNextLinkAndCount.json b/odata2-lib/odata-client-core/src/test/resources/JsonBuildingWithInlineRoomsAndNextLinkAndCount.json
new file mode 100644
index 0000000..4e2929e
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/resources/JsonBuildingWithInlineRoomsAndNextLinkAndCount.json
@@ -0,0 +1,39 @@
+{
+	"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" : {
+			"__count" : "1",
+			"results" : [{
+					"__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"
+						}
+					}
+				}
+			],
+			"__next" : "nextLink"
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/resources/JsonBuildingWithInlineRoomsClientCase.json
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/resources/JsonBuildingWithInlineRoomsClientCase.json b/odata2-lib/odata-client-core/src/test/resources/JsonBuildingWithInlineRoomsClientCase.json
new file mode 100644
index 0000000..68de707
--- /dev/null
+++ b/odata2-lib/odata-client-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"
+						}
+					}
+				}
+			]
+	}
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/resources/JsonBuildingWithoutD.json
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/resources/JsonBuildingWithoutD.json b/odata2-lib/odata-client-core/src/test/resources/JsonBuildingWithoutD.json
new file mode 100644
index 0000000..8712a1c
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/resources/JsonBuildingWithoutD.json
@@ -0,0 +1,15 @@
+{
+		"__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" : {
+			"__deferred" : {
+				"uri" : "http://localhost:8080/ReferenceScenario.svc/Buildings('1')/nb_Rooms"
+			}
+		}
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/resources/JsonEmployee.json
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/resources/JsonEmployee.json b/odata2-lib/odata-client-core/src/test/resources/JsonEmployee.json
new file mode 100644
index 0000000..868f58a
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/resources/JsonEmployee.json
@@ -0,0 +1,48 @@
+{
+	"d" : {
+		"__metadata" : {
+			"id" : "http://localhost:8080/ReferenceScenario.svc/Employees('1')",
+			"uri" : "http://localhost:8080/ReferenceScenario.svc/Employees('1')",
+			"type" : "RefScenario.Employee",
+			"content_type" : "image/jpeg",
+			"media_src" : "Employees('1')/$value",
+			"edit_media" : "http://localhost:8080/ReferenceScenario.svc/Employees('1')/$value"
+		},
+		"EmployeeId" : "1",
+		"EmployeeName" : "Walter Winter",
+		"ManagerId" : "1",
+		"RoomId" : "1",
+		"TeamId" : "1",
+		"Location" : {
+			"__metadata" : {
+				"type" : "RefScenario.c_Location"
+			},
+			"City" : {
+				"__metadata" : {
+					"type" : "RefScenario.c_City"
+				},
+				"PostalCode" : "69124",
+				"CityName" : "Heidelberg"
+			},
+			"Country" : "Germany"
+		},
+		"Age" : 52,
+		"EntryDate" : "\/Date(915148800000)\/",
+		"ImageUrl" : "Employees('1')/$value",
+		"ne_Manager" : {
+			"__deferred" : {
+				"uri" : "http://localhost:8080/ReferenceScenario.svc/Employees('1')/ne_Manager"
+			}
+		},
+		"ne_Team" : {
+			"__deferred" : {
+				"uri" : "http://localhost:8080/ReferenceScenario.svc/Employees('1')/ne_Team"
+			}
+		},
+		"ne_Room" : {
+			"__deferred" : {
+				"uri" : "http://localhost:8080/ReferenceScenario.svc/Employees('1')/ne_Room"
+			}
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/resources/JsonEmployeeContentOnly.json
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/resources/JsonEmployeeContentOnly.json b/odata2-lib/odata-client-core/src/test/resources/JsonEmployeeContentOnly.json
new file mode 100644
index 0000000..9352a29
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/resources/JsonEmployeeContentOnly.json
@@ -0,0 +1,25 @@
+{
+	"d" : {
+		"EmployeeId" : "1",
+		"EmployeeName" : "Walter Winter",
+		"ManagerId" : "1",
+		"RoomId" : "1",
+		"TeamId" : "1",
+		"Location" : {
+			"__metadata" : {
+				"type" : "RefScenario.c_Location"
+			},
+			"City" : {
+				"__metadata" : {
+					"type" : "RefScenario.c_City"
+				},
+				"PostalCode" : "69124",
+				"CityName" : "Heidelberg"
+			},
+			"Country" : "Germany"
+		},
+		"Age" : 52,
+		"EntryDate" : "\/Date(915148800000)\/",
+		"ImageUrl" : "Employees('1')/$value"
+	}
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/resources/JsonEmployeeContentOnlyWithAdditionalLink.json
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/resources/JsonEmployeeContentOnlyWithAdditionalLink.json b/odata2-lib/odata-client-core/src/test/resources/JsonEmployeeContentOnlyWithAdditionalLink.json
new file mode 100644
index 0000000..fb90c14
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/resources/JsonEmployeeContentOnlyWithAdditionalLink.json
@@ -0,0 +1,30 @@
+{
+	"d" : {
+		"EmployeeId" : "1",
+		"EmployeeName" : "Walter Winter",
+		"ManagerId" : "1",
+		"RoomId" : "1",
+		"TeamId" : "1",
+		"Location" : {
+			"__metadata" : {
+				"type" : "RefScenario.c_Location"
+			},
+			"City" : {
+				"__metadata" : {
+					"type" : "RefScenario.c_City"
+				},
+				"PostalCode" : "69124",
+				"CityName" : "Heidelberg"
+			},
+			"Country" : "Germany"
+		},
+		"Age" : 52,
+		"EntryDate" : "\/Date(915148800000)\/",
+		"ImageUrl" : "Employees('1')/$value",
+		"ne_Manager" : {
+			"__deferred" : {
+				"uri" : "http://host:8080/ReferenceScenario.svc/Managers('1')"
+			}
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/resources/JsonEmployeeInlineRoomBuilding.json
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/resources/JsonEmployeeInlineRoomBuilding.json b/odata2-lib/odata-client-core/src/test/resources/JsonEmployeeInlineRoomBuilding.json
new file mode 100644
index 0000000..8f35315
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/resources/JsonEmployeeInlineRoomBuilding.json
@@ -0,0 +1,75 @@
+{
+  "d": {
+    "__metadata": {
+      "id": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Employees('1')",
+      "uri": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Employees('1')",
+      "type": "RefScenario.Employee",
+      "content_type": "image/jpeg",
+      "media_src": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Employees('1')/$value",
+      "edit_media": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Employees('1')/$value"
+    },
+    "EmployeeId": "1",
+    "EmployeeName": "Walter Winter",
+    "ManagerId": "1",
+    "RoomId": "1",
+    "TeamId": "1",
+    "Location": {
+      "__metadata": {
+        "type": "RefScenario.c_Location"
+      },
+      "City": {
+        "__metadata": {
+          "type": "RefScenario.c_City"
+        },
+        "PostalCode": "69124",
+        "CityName": "Heidelberg"
+      },
+      "Country": "Germany"
+    },
+    "Age": 52,
+    "EntryDate": "/Date(915148800000)/",
+    "ImageUrl": "Employees('1')/$value",
+    "ne_Manager": {
+      "__deferred": {
+        "uri": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Employees('1')/ne_Manager"
+      }
+    },
+    "ne_Team": {
+      "__deferred": {
+        "uri": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Employees('1')/ne_Team"
+      }
+    },
+    "ne_Room": {
+      "__metadata": {
+        "id": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Rooms('1')",
+        "uri": "http://localhost:8080/olingo-odata2-ref-web/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/olingo-odata2-ref-web/ReferenceScenario.svc/Rooms('1')/nr_Employees"
+        }
+      },
+      "nr_Building": {
+        "__metadata": {
+          "id": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Buildings('1')",
+          "uri": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Buildings('1')",
+          "type": "RefScenario.Building"
+        },
+        "Id": "1",
+        "Name": "Building 1",
+        "Image": null,
+        "nb_Rooms": {
+          "__deferred": {
+            "uri": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Buildings('1')/nb_Rooms"
+          }
+        }
+      }
+    }
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/resources/JsonEmployeeWithInlineTeam.json
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/resources/JsonEmployeeWithInlineTeam.json b/odata2-lib/odata-client-core/src/test/resources/JsonEmployeeWithInlineTeam.json
new file mode 100644
index 0000000..07f4c34
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/resources/JsonEmployeeWithInlineTeam.json
@@ -0,0 +1,58 @@
+{
+	"d" : {
+		"__metadata" : {
+			"id" : "http://localhost:8080/ReferenceScenario.svc/Employees('1')",
+			"uri" : "http://localhost:8080/ReferenceScenario.svc/Employees('1')",
+			"type" : "RefScenario.Employee",
+			"content_type" : "image/jpeg",
+			"media_src" : "Employees('1')/$value",
+			"edit_media" : "http://localhost:8080/ReferenceScenario.svc/Employees('1')/$value"
+		},
+		"EmployeeId" : "1",
+		"EmployeeName" : "Walter Winter",
+		"ManagerId" : "1",
+		"RoomId" : "1",
+		"TeamId" : "1",
+		"Location" : {
+			"__metadata" : {
+				"type" : "RefScenario.c_Location"
+			},
+			"City" : {
+				"__metadata" : {
+					"type" : "RefScenario.c_City"
+				},
+				"PostalCode" : "69124",
+				"CityName" : "Heidelberg"
+			},
+			"Country" : "Germany"
+		},
+		"Age" : 52,
+		"EntryDate" : "\/Date(915148800000)\/",
+		"ImageUrl" : "Employees('1')/$value",
+		"ne_Manager" : {
+			"__deferred" : {
+				"uri" : "http://localhost:8080/ReferenceScenario.svc/Employees('1')/ne_Manager"
+			}
+		},
+		"ne_Team" : {
+			"__metadata" : {
+				"id" : "http://localhost:8080/ReferenceScenario.svc/Teams('1')",
+				"uri" : "http://localhost:8080/ReferenceScenario.svc/Teams('1')",
+				"type" : "RefScenario.Team"
+			},
+			"Id" : "1",
+			"Name" : "Team 1",
+			"isScrumTeam" : false,
+			"nt_Employees" : {
+				"__deferred" : {
+					"uri" : "http://localhost:8080/ReferenceScenario.svc/Teams('1')/nt_Employees"
+				}
+			}
+		},
+		"ne_Room" : {
+			"__deferred" : {
+				"uri" : "http://localhost:8080/ReferenceScenario.svc/Employees('1')/ne_Room"
+			}
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/resources/JsonInlineRoomWithInlineBuilding.json
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/resources/JsonInlineRoomWithInlineBuilding.json b/odata2-lib/odata-client-core/src/test/resources/JsonInlineRoomWithInlineBuilding.json
new file mode 100644
index 0000000..a9cf63c
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/resources/JsonInlineRoomWithInlineBuilding.json
@@ -0,0 +1,75 @@
+{
+	"d" : {
+		"__metadata" : {
+			"id" : "http://localhost:8080/ReferenceScenario.svc/Employees('1')",
+			"uri" : "http://localhost:8080/ReferenceScenario.svc/Employees('1')",
+			"type" : "RefScenario.Employee",
+			"content_type" : "image/jpeg",
+			"media_src" : "Employees('1')/$value",
+			"edit_media" : "http://localhost:8080/ReferenceScenario.svc/Employees('1')/$value"
+		},
+		"EmployeeId" : "1",
+		"EmployeeName" : "Walter Winter",
+		"ManagerId" : "1",
+		"RoomId" : "1",
+		"TeamId" : "1",
+		"Location" : {
+			"__metadata" : {
+				"type" : "RefScenario.c_Location"
+			},
+			"City" : {
+				"__metadata" : {
+					"type" : "RefScenario.c_City"
+				},
+				"PostalCode" : "69124",
+				"CityName" : "Heidelberg"
+			},
+			"Country" : "Germany"
+		},
+		"Age" : 52,
+		"EntryDate" : "\/Date(915148800000)\/",
+		"ImageUrl" : "Employees('1')/$value",
+		"ne_Manager" : {
+			"__deferred" : {
+				"uri" : "http://localhost:8080/ReferenceScenario.svc/Employees('1')/ne_Manager"
+			}
+		},
+		"ne_Team" : {
+			"__deferred" : {
+				"uri" : "http://localhost:8080/ReferenceScenario.svc/Employees('1')/ne_Team"
+			}
+		},
+		"ne_Room" : {
+			"__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" : {
+				"__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" : {
+					"__deferred" : {
+						"uri" : "http://localhost:8080/ReferenceScenario.svc/Buildings('1')/nb_Rooms"
+					}
+				}
+			}
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/resources/JsonInlineRoomWithInlineNull.json
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/resources/JsonInlineRoomWithInlineNull.json b/odata2-lib/odata-client-core/src/test/resources/JsonInlineRoomWithInlineNull.json
new file mode 100644
index 0000000..a4b8c5e
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/resources/JsonInlineRoomWithInlineNull.json
@@ -0,0 +1,44 @@
+{
+	"d" : {
+		"__metadata" : {
+			"id" : "http://localhost:8080/ReferenceScenario.svc/Employees('1')",
+			"uri" : "http://localhost:8080/ReferenceScenario.svc/Employees('1')",
+			"type" : "RefScenario.Employee",
+			"content_type" : "image/jpeg",
+			"media_src" : "Employees('1')/$value",
+			"edit_media" : "http://localhost:8080/ReferenceScenario.svc/Employees('1')/$value"
+		},
+		"EmployeeId" : "1",
+		"EmployeeName" : "Walter Winter",
+		"ManagerId" : "1",
+		"RoomId" : "1",
+		"TeamId" : "1",
+		"Location" : {
+			"__metadata" : {
+				"type" : "RefScenario.c_Location"
+			},
+			"City" : {
+				"__metadata" : {
+					"type" : "RefScenario.c_City"
+				},
+				"PostalCode" : "69124",
+				"CityName" : "Heidelberg"
+			},
+			"Country" : "Germany"
+		},
+		"Age" : 52,
+		"EntryDate" : "\/Date(915148800000)\/",
+		"ImageUrl" : "Employees('1')/$value",
+		"ne_Manager" : {
+			"__deferred" : {
+				"uri" : "http://localhost:8080/ReferenceScenario.svc/Employees('1')/ne_Manager"
+			}
+		},
+		"ne_Team" : {
+			"__deferred" : {
+				"uri" : "http://localhost:8080/ReferenceScenario.svc/Employees('1')/ne_Team"
+			}
+		},
+		"ne_Room" : null
+	}
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/resources/JsonInvalidTeamDoubleNameProperty.json
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/resources/JsonInvalidTeamDoubleNameProperty.json b/odata2-lib/odata-client-core/src/test/resources/JsonInvalidTeamDoubleNameProperty.json
new file mode 100644
index 0000000..7b96837
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/resources/JsonInvalidTeamDoubleNameProperty.json
@@ -0,0 +1,18 @@
+{
+	"d" : {
+		"__metadata" : {
+			"id" : "http://localhost:8080/ReferenceScenario.svc/Teams('1')",
+			"uri" : "http://localhost:8080/ReferenceScenario.svc/Teams('1')",
+			"type" : "RefScenario.Team"
+		},
+		"Id" : "1",
+		"Name" : "Team 1",
+		"Name" : "Wrong TeamName",
+		"isScrumTeam" : false,
+		"nt_Employees" : {
+			"__deferred" : {
+				"uri" : "http://localhost:8080/ReferenceScenario.svc/Teams('1')/nt_Employees"
+			}
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/resources/JsonRoom.json
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/resources/JsonRoom.json b/odata2-lib/odata-client-core/src/test/resources/JsonRoom.json
new file mode 100644
index 0000000..806aef2
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/resources/JsonRoom.json
@@ -0,0 +1,24 @@
+{
+	"d" : {
+		"__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"
+			}
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/resources/JsonRoomContentOnly.json
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/resources/JsonRoomContentOnly.json b/odata2-lib/odata-client-core/src/test/resources/JsonRoomContentOnly.json
new file mode 100644
index 0000000..f8c741a
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/resources/JsonRoomContentOnly.json
@@ -0,0 +1,8 @@
+{
+	"d" : {
+		"Id" : "1",
+		"Name" : "Room 1",
+		"Seats" : 1,
+		"Version" : 1
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/resources/JsonRoomContentOnlyWithAdditionalLink.json
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/resources/JsonRoomContentOnlyWithAdditionalLink.json b/odata2-lib/odata-client-core/src/test/resources/JsonRoomContentOnlyWithAdditionalLink.json
new file mode 100644
index 0000000..7a511b6
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/resources/JsonRoomContentOnlyWithAdditionalLink.json
@@ -0,0 +1,13 @@
+{
+	"d" : {
+		"Id" : "1",
+		"Name" : "Room 1",
+		"Seats" : 1,
+		"Version" : 1,
+		"nr_Building" : {
+			"__deferred" : {
+				"uri" : "http://host:8080/ReferenceScenario.svc/Buildings('1')"
+			}
+		}
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/test/resources/JsonRoom_EmptyInlineEmployeesToTeam.json
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/test/resources/JsonRoom_EmptyInlineEmployeesToTeam.json b/odata2-lib/odata-client-core/src/test/resources/JsonRoom_EmptyInlineEmployeesToTeam.json
new file mode 100644
index 0000000..8495fab
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/test/resources/JsonRoom_EmptyInlineEmployeesToTeam.json
@@ -0,0 +1,22 @@
+{
+  "d": {
+    "__metadata": {
+      "id": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Rooms('10')",
+      "uri": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Rooms('10')",
+      "type": "RefScenario.Room",
+      "etag": "W/\"1\""
+    },
+    "Id": "10",
+    "Name": "Room 10",
+    "Seats": 6,
+    "Version": 1,
+    "nr_Employees": {
+      "results": []
+    },
+    "nr_Building": {
+      "__deferred": {
+        "uri": "http://localhost:8080/olingo-odata2-ref-web/ReferenceScenario.svc/Rooms('10')/nr_Building"
+      }
+    }
+  }
+}
\ No newline at end of file