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/"1"">
+ <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/"0"">
+ <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/"0"">
+ <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/"0"">
+ <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/"0"">
+ <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/"0"">
+ <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/"0"">
+ <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/"0"">
+ <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/"0"">
+ <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/"0"">
+ <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/"1"">
+ <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/"1"">
+ <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/"1"\">"
+ +
+ " <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/"1"\">"
+ +
+ " <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/"1"\">"
+ +
+ " <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/"1"\">"
+ +
+ " <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/"1"\">"
+ +
+ " <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/"1"\" 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/"1"\" 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/"1"\">"
+ +
+ "</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/"1"\">"
+ +
+ "</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/"1"\">"
+ +
+ " <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/"1"\">"
+ +
+ " <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/"1"\">"
+ +
+ " <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/"1"\">"
+ +
+ " <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/"1"\">" +
+ "" +
+ " <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/"1"\">" +
+ "" +
+ " <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/"1"\">"
+ +
+ " <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/"1"\">"
+ +
+ ""
+ +
+ " <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/"1"\">" +
+ " <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/"1"\">" +
+ "" +
+ " <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/"1"\">" +
+ "" +
+ " <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/"1"\">" +
+ "" +
+ " <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/"1"\">" +
+ "" +
+ " <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/"1"\">"
+ +
+ " <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/"1"\">"
+ +
+ " <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/"1"\">"
+ +
+ " <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'¬aparameter=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