You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by ra...@apache.org on 2016/06/02 17:21:54 UTC

[1/3] olingo-odata4 git commit: OLINGO-567: Support for odata.metadata=full

Repository: olingo-odata4
Updated Branches:
  refs/heads/OLINGO-567-rareddy [created] eaceb01d1


http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/eaceb01d/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/xml/ODataXmlSerializerTest.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/xml/ODataXmlSerializerTest.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/xml/ODataXmlSerializerTest.java
index bd24f27..9a830d3 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/xml/ODataXmlSerializerTest.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/xml/ODataXmlSerializerTest.java
@@ -162,11 +162,171 @@ public class ODataXmlSerializerTest {
         "      </d:PropertyTimeOfDay>\n" +
         "    </m:properties>\n" +
         "  </a:content>\n" +
+        "   <m:action metadata=\"#olingo.odata.test1.BAETAllPrimRT\" "+
+        "      title=\"olingo.odata.test1.BAETAllPrimRT\" "+
+        "      target=\"ESAllPrim(32767)/olingo.odata.test1.BAETAllPrimRT\" />\n" + 
         "</a:entry>";
     checkXMLEqual(expected, resultString);
   }
 
   @Test
+  public void entitySetSimple() throws Exception {
+    final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim");
+    final EntityCollection entityCollection = data.readAll(edmEntitySet);
+    long currentTimeMillis = System.currentTimeMillis();
+    InputStream result = serializer.entityCollection(metadata, edmEntitySet.getEntityType(), entityCollection,
+        EntityCollectionSerializerOptions.with()
+            .contextURL(ContextURL.with().entitySet(edmEntitySet).build())
+            .build()).getContent();
+    final String resultString = IOUtils.toString(result);
+    String expected = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + 
+        "<a:feed xmlns:a=\"http://www.w3.org/2005/Atom\" "
+        + "xmlns:d=\"http://docs.oasis-open.org/odata/ns/data\" "
+        + "xmlns:m=\"http://docs.oasis-open.org/odata/ns/metadata\" "
+        + "m:context=\"$metadata#ESAllPrim\" m:metadata-etag=\"metadataETag\">\n" + 
+        "   <m:action metadata=\"#olingo.odata.test1.BAESAllPrimRTETAllPrim\" "
+        + "title=\"olingo.odata.test1.BAESAllPrimRTETAllPrim\" "
+        + "target=\"ESAllPrim/olingo.odata.test1.BAESAllPrimRTETAllPrim\" />\n" + 
+        "   <m:action metadata=\"#olingo.odata.test1.BAESAllPrimRT\" "
+        + "title=\"olingo.odata.test1.BAESAllPrimRT\" "
+        + "target=\"ESAllPrim/olingo.odata.test1.BAESAllPrimRT\" />\n" + 
+        "   <m:function metadata=\"#olingo.odata.test1.BFNESAllPrimRTCTAllPrim\" "
+        + "title=\"olingo.odata.test1.BFNESAllPrimRTCTAllPrim\" "
+        + "target=\"ESAllPrim/olingo.odata.test1.BFNESAllPrimRTCTAllPrim\" />\n" + 
+        "   <m:function metadata=\"#olingo.odata.test1.BFNESAllPrimRTCTAllPrim(Param2)\" "
+        + "title=\"olingo.odata.test1.BFNESAllPrimRTCTAllPrim\" "
+        + "target=\"ESAllPrim/olingo.odata.test1.BFNESAllPrimRTCTAllPrim(Param2=@Param2)\" />\n" + 
+        "   <a:entry>\n" + 
+        "      <a:id>ESAllPrim(32767)</a:id>\n" + 
+        "      <a:title />\n" + 
+        "      <a:summary />\n" + 
+        "      <a:updated>"+ UPDATED_FORMAT.format(new Date(currentTimeMillis)) +"</a:updated>\n" + 
+        "      <a:author>\n" + 
+        "         <a:name />\n" + 
+        "      </a:author>\n" + 
+        "      <a:link rel=\"edit\" href=\"ESAllPrim(32767)\" />\n" + 
+        "      <a:link rel=\"http://docs.oasis-open.org/odata/ns/related/NavPropertyETTwoPrimOne\" "
+        + "type=\"application/atom+xml;type=entry\" title=\"NavPropertyETTwoPrimOne\" "
+        + "href=\"ESTwoPrim(32767)\" />\n" + 
+        "      <a:link rel=\"http://docs.oasis-open.org/odata/ns/related/NavPropertyETTwoPrimMany\" "
+        + "type=\"application/atom+xml;type=feed\" title=\"NavPropertyETTwoPrimMany\" "
+        + "href=\"ESAllPrim(32767)/NavPropertyETTwoPrimMany\" />\n" + 
+        "      <a:category scheme=\"http://docs.oasis-open.org/odata/ns/scheme\" "
+        + "term=\"#olingo.odata.test1.ETAllPrim\" />\n" + 
+        "      <a:content type=\"application/xml\">\n" + 
+        "         <m:properties>\n" + 
+        "            <d:PropertyInt16 m:type=\"Int16\">32767</d:PropertyInt16>\n" + 
+        "            <d:PropertyString>First Resource - positive values</d:PropertyString>\n" + 
+        "            <d:PropertyBoolean m:type=\"Boolean\">true</d:PropertyBoolean>\n" + 
+        "            <d:PropertyByte m:type=\"Byte\">255</d:PropertyByte>\n" + 
+        "            <d:PropertySByte m:type=\"SByte\">127</d:PropertySByte>\n" + 
+        "            <d:PropertyInt32 m:type=\"Int32\">2147483647</d:PropertyInt32>\n" + 
+        "            <d:PropertyInt64 m:type=\"Int64\">9223372036854775807</d:PropertyInt64>\n" + 
+        "            <d:PropertySingle m:type=\"Single\">1.79E20</d:PropertySingle>\n" + 
+        "            <d:PropertyDouble m:type=\"Double\">-1.79E19</d:PropertyDouble>\n" + 
+        "            <d:PropertyDecimal m:type=\"Decimal\">34</d:PropertyDecimal>\n" + 
+        "            <d:PropertyBinary m:type=\"Binary\">ASNFZ4mrze8=</d:PropertyBinary>\n" + 
+        "            <d:PropertyDate m:type=\"Date\">2012-12-03</d:PropertyDate>\n" + 
+        "            <d:PropertyDateTimeOffset m:type=\"DateTimeOffset\">2012-12-03T07:16:23Z"
+        + "</d:PropertyDateTimeOffset>\n" + 
+        "            <d:PropertyDuration m:type=\"Duration\">PT6S</d:PropertyDuration>\n" + 
+        "            <d:PropertyGuid m:type=\"Guid\">01234567-89ab-cdef-0123-456789abcdef</d:PropertyGuid>\n" + 
+        "            <d:PropertyTimeOfDay m:type=\"TimeOfDay\">03:26:05</d:PropertyTimeOfDay>\n" + 
+        "         </m:properties>\n" + 
+        "      </a:content>\n" + 
+        "      <m:action metadata=\"#olingo.odata.test1.BAETAllPrimRT\" "
+        + "title=\"olingo.odata.test1.BAETAllPrimRT\" "
+        + "target=\"ESAllPrim(32767)/olingo.odata.test1.BAETAllPrimRT\" />\n" + 
+        "   </a:entry>\n" + 
+        "   <a:entry>\n" + 
+        "      <a:id>ESAllPrim(-32768)</a:id>\n" + 
+        "      <a:title />\n" + 
+        "      <a:summary />\n" + 
+        "      <a:updated>"+ UPDATED_FORMAT.format(new Date(currentTimeMillis)) +"</a:updated>\n" + 
+        "      <a:author>\n" + 
+        "         <a:name />\n" + 
+        "      </a:author>\n" + 
+        "      <a:link rel=\"edit\" href=\"ESAllPrim(-32768)\" />\n" + 
+        "      <a:link rel=\"http://docs.oasis-open.org/odata/ns/related/NavPropertyETTwoPrimOne\" "
+        + "type=\"application/atom+xml;type=feed\" title=\"NavPropertyETTwoPrimOne\" "
+        + "href=\"ESAllPrim(-32768)/NavPropertyETTwoPrimOne\" />\n" + 
+        "      <a:link rel=\"http://docs.oasis-open.org/odata/ns/related/NavPropertyETTwoPrimMany\" "
+        + "type=\"application/atom+xml;type=feed\" title=\"NavPropertyETTwoPrimMany\" "
+        + "href=\"ESAllPrim(-32768)/NavPropertyETTwoPrimMany\" />\n" + 
+        "      <a:category scheme=\"http://docs.oasis-open.org/odata/ns/scheme\" "
+        + "term=\"#olingo.odata.test1.ETAllPrim\" />\n" + 
+        "      <a:content type=\"application/xml\">\n" + 
+        "         <m:properties>\n" + 
+        "            <d:PropertyInt16 m:type=\"Int16\">-32768</d:PropertyInt16>\n" + 
+        "            <d:PropertyString>Second Resource - negative values</d:PropertyString>\n" + 
+        "            <d:PropertyBoolean m:type=\"Boolean\">false</d:PropertyBoolean>\n" + 
+        "            <d:PropertyByte m:type=\"Byte\">0</d:PropertyByte>\n" + 
+        "            <d:PropertySByte m:type=\"SByte\">-128</d:PropertySByte>\n" + 
+        "            <d:PropertyInt32 m:type=\"Int32\">-2147483648</d:PropertyInt32>\n" + 
+        "            <d:PropertyInt64 m:type=\"Int64\">-9223372036854775808</d:PropertyInt64>\n" + 
+        "            <d:PropertySingle m:type=\"Single\">-1.79E8</d:PropertySingle>\n" + 
+        "            <d:PropertyDouble m:type=\"Double\">-179000.0</d:PropertyDouble>\n" + 
+        "            <d:PropertyDecimal m:type=\"Decimal\">-34</d:PropertyDecimal>\n" + 
+        "            <d:PropertyBinary m:type=\"Binary\">ASNFZ4mrze8=</d:PropertyBinary>\n" + 
+        "            <d:PropertyDate m:type=\"Date\">2015-11-05</d:PropertyDate>\n" + 
+        "            <d:PropertyDateTimeOffset m:type=\"DateTimeOffset\">2005-12-03T07:17:08Z"
+        + "</d:PropertyDateTimeOffset>\n" + 
+        "            <d:PropertyDuration m:type=\"Duration\">PT9S</d:PropertyDuration>\n" + 
+        "            <d:PropertyGuid m:type=\"Guid\">76543201-23ab-cdef-0123-456789dddfff</d:PropertyGuid>\n" + 
+        "            <d:PropertyTimeOfDay m:type=\"TimeOfDay\">23:49:14</d:PropertyTimeOfDay>\n" + 
+        "         </m:properties>\n" + 
+        "      </a:content>\n" + 
+        "      <m:action metadata=\"#olingo.odata.test1.BAETAllPrimRT\" "
+        + "title=\"olingo.odata.test1.BAETAllPrimRT\" "
+        + "target=\"ESAllPrim(-32768)/olingo.odata.test1.BAETAllPrimRT\" />\n" + 
+        "   </a:entry>\n" + 
+        "   <a:entry>\n" + 
+        "      <a:id>ESAllPrim(0)</a:id>\n" + 
+        "      <a:title />\n" + 
+        "      <a:summary />\n" + 
+        "      <a:updated>"+ UPDATED_FORMAT.format(new Date(currentTimeMillis)) +"</a:updated>\n" + 
+        "      <a:author>\n" + 
+        "         <a:name />\n" + 
+        "      </a:author>\n" + 
+        "      <a:link rel=\"edit\" href=\"ESAllPrim(0)\" />\n" + 
+        "      <a:link rel=\"http://docs.oasis-open.org/odata/ns/related/NavPropertyETTwoPrimOne\" "
+        + "type=\"application/atom+xml;type=feed\" title=\"NavPropertyETTwoPrimOne\" "
+        + "href=\"ESAllPrim(0)/NavPropertyETTwoPrimOne\" />\n" + 
+        "      <a:link rel=\"http://docs.oasis-open.org/odata/ns/related/NavPropertyETTwoPrimMany\" "
+        + "type=\"application/atom+xml;type=feed\" title=\"NavPropertyETTwoPrimMany\" "
+        + "href=\"ESAllPrim(0)/NavPropertyETTwoPrimMany\" />\n" + 
+        "      <a:category scheme=\"http://docs.oasis-open.org/odata/ns/scheme\" "
+        + "term=\"#olingo.odata.test1.ETAllPrim\" />\n" + 
+        "      <a:content type=\"application/xml\">\n" + 
+        "         <m:properties>\n" + 
+        "            <d:PropertyInt16 m:type=\"Int16\">0</d:PropertyInt16>\n" + 
+        "            <d:PropertyString />\n" + 
+        "            <d:PropertyBoolean m:type=\"Boolean\">false</d:PropertyBoolean>\n" + 
+        "            <d:PropertyByte m:type=\"Byte\">0</d:PropertyByte>\n" + 
+        "            <d:PropertySByte m:type=\"SByte\">0</d:PropertySByte>\n" + 
+        "            <d:PropertyInt32 m:type=\"Int32\">0</d:PropertyInt32>\n" + 
+        "            <d:PropertyInt64 m:type=\"Int64\">0</d:PropertyInt64>\n" + 
+        "            <d:PropertySingle m:type=\"Single\">0.0</d:PropertySingle>\n" + 
+        "            <d:PropertyDouble m:type=\"Double\">0.0</d:PropertyDouble>\n" + 
+        "            <d:PropertyDecimal m:type=\"Decimal\">0</d:PropertyDecimal>\n" + 
+        "            <d:PropertyBinary m:type=\"Binary\" />\n" + 
+        "            <d:PropertyDate m:type=\"Date\">1970-01-01</d:PropertyDate>\n" + 
+        "            <d:PropertyDateTimeOffset m:type=\"DateTimeOffset\">2005-12-03T00:00:00Z"
+        + "</d:PropertyDateTimeOffset>\n" + 
+        "            <d:PropertyDuration m:type=\"Duration\">PT0S</d:PropertyDuration>\n" + 
+        "            <d:PropertyGuid m:type=\"Guid\">76543201-23ab-cdef-0123-456789cccddd</d:PropertyGuid>\n" + 
+        "            <d:PropertyTimeOfDay m:type=\"TimeOfDay\">00:01:01</d:PropertyTimeOfDay>\n" + 
+        "         </m:properties>\n" + 
+        "      </a:content>\n" + 
+        "      <m:action metadata=\"#olingo.odata.test1.BAETAllPrimRT\" "
+        + "title=\"olingo.odata.test1.BAETAllPrimRT\" "
+        + "target=\"ESAllPrim(0)/olingo.odata.test1.BAETAllPrimRT\" />\n" + 
+        "   </a:entry>\n" + 
+        "</a:feed>";
+    checkXMLEqual(expected, resultString);
+  }  
+  
+  @Test
   public void entityAllPrimAllNull() throws Exception {
     final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim");
     Entity entity = data.readAll(edmEntitySet).getEntities().get(0);
@@ -223,6 +383,9 @@ public class ODataXmlSerializerTest {
         "      <d:PropertyTimeOfDay m:null=\"true\" />\n" +
         "    </m:properties>\n" +
         "  </a:content>\n" +
+        "   <m:action metadata=\"#olingo.odata.test1.BAETAllPrimRT\" "+
+        "      title=\"olingo.odata.test1.BAETAllPrimRT\" "+
+        "      target=\"ESAllPrim(32767)/olingo.odata.test1.BAETAllPrimRT\" />\n" + 
         "</a:entry>\n" +
         "";
     checkXMLEqual(expected, resultString);
@@ -950,7 +1113,7 @@ public class ODataXmlSerializerTest {
                     .suffix(Suffix.ENTITY).build())
                 .select(select)
                 .build()).getContent();
-    final String resultString = IOUtils.toString(result);
+    final String resultString = IOUtils.toString(result);    
     final String expectedResult = "<?xml version='1.0' encoding='UTF-8'?>\n" +
         "<a:entry xmlns:a=\"http://www.w3.org/2005/Atom\"\n" +
         "  xmlns:m=\"http://docs.oasis-open.org/odata/ns/metadata\"\n" +
@@ -981,6 +1144,9 @@ public class ODataXmlSerializerTest {
         "      <d:PropertyDate m:type=\"Date\">2012-12-03</d:PropertyDate>\n" +
         "    </m:properties>\n" +
         "  </a:content>\n" +
+        "   <m:action metadata=\"#olingo.odata.test1.BAETAllPrimRT\" "+
+        "      title=\"olingo.odata.test1.BAETAllPrimRT\" "+
+        "      target=\"ESAllPrim(32767)/olingo.odata.test1.BAETAllPrimRT\" />\n" + 
         "</a:entry>";
     checkXMLEqual(expectedResult, resultString);
   }
@@ -1282,6 +1448,9 @@ public class ODataXmlSerializerTest {
         "            </d:PropertyTimeOfDay>\n" +
         "          </m:properties>\n" +
         "        </a:content>\n" +
+        "        <m:action metadata=\"#olingo.odata.test1.BAETAllPrimRT\" "+
+        "          title=\"olingo.odata.test1.BAETAllPrimRT\" "+
+        "          target=\"ESAllPrim(32767)/olingo.odata.test1.BAETAllPrimRT\" />\n" +               
         "      </a:entry>\n" +
         "    </m:inline>\n" +
         "  </a:link>\n" +
@@ -1321,7 +1490,7 @@ public class ODataXmlSerializerTest {
                     .suffix(Suffix.ENTITY).build())
                 .expand(expand)
                 .build()).getContent();
-    final String resultString = IOUtils.toString(inputStream);
+    final String resultString = IOUtils.toString(inputStream);    
     String expected = "<?xml version='1.0' encoding='UTF-8'?>\n" +
         "<a:entry xmlns:a=\"http://www.w3.org/2005/Atom\" "
         + "xmlns:m=\"http://docs.oasis-open.org/odata/ns/metadata\"\n" +
@@ -1365,6 +1534,9 @@ public class ODataXmlSerializerTest {
         "            <d:PropertyDate m:type=\"Date\">2012-12-03</d:PropertyDate>\n" +
         "          </m:properties>\n" +
         "        </a:content>\n" +
+        "        <m:action metadata=\"#olingo.odata.test1.BAETAllPrimRT\" "+
+        "          title=\"olingo.odata.test1.BAETAllPrimRT\" "+
+        "          target=\"ESAllPrim(32767)/olingo.odata.test1.BAETAllPrimRT\" />\n" + 
         "      </a:entry>\n" +
         "    </m:inline>\n" +
         "  </a:link>\n" +
@@ -1498,6 +1670,9 @@ public class ODataXmlSerializerTest {
         "      <d:PropertySByte m:type=\"SByte\">127</d:PropertySByte>\n" +
         "    </m:properties>\n" +
         "  </a:content>\n" +
+        "   <m:action metadata=\"#olingo.odata.test1.BAETAllPrimRT\" "+
+        "      title=\"olingo.odata.test1.BAETAllPrimRT\" "+
+        "      target=\"ESAllPrim(32767)/olingo.odata.test1.BAETAllPrimRT\" />\n" + 
         "</a:entry>\n" +
         "";
     checkXMLEqual(expected, resultString);
@@ -1560,6 +1735,9 @@ public class ODataXmlSerializerTest {
         "      </d:PropertyTimeOfDay>\n" +
         "    </m:properties>\n" +
         "  </a:content>\n" +
+        "   <m:action metadata=\"#olingo.odata.test1.BAETAllPrimRT\" "+
+        "      title=\"olingo.odata.test1.BAETAllPrimRT\" "+
+        "      target=\"ESAllPrim(-32768)/olingo.odata.test1.BAETAllPrimRT\" />\n" + 
         "</a:entry>";
     checkXMLEqual(expected, resultString);
   }
@@ -1644,6 +1822,9 @@ public class ODataXmlSerializerTest {
         "              <d:PropertyInt32 m:type=\"Int32\">-2147483648</d:PropertyInt32>\n" +
         "            </m:properties>\n" +
         "          </a:content>\n" +
+        "        <m:action metadata=\"#olingo.odata.test1.BAETAllPrimRT\" "+
+        "          title=\"olingo.odata.test1.BAETAllPrimRT\" "+
+        "          target=\"ESAllPrim(-32768)/olingo.odata.test1.BAETAllPrimRT\" />\n" + 
         "        </a:entry>\n" +
         "        <a:entry>\n" +
         "          <a:id>ESAllPrim(0)</a:id>\n" +
@@ -1758,6 +1939,9 @@ public class ODataXmlSerializerTest {
         "              <d:PropertyInt32 m:type=\"Int32\">0</d:PropertyInt32>\n" +
         "            </m:properties>\n" +
         "          </a:content>\n" +
+        "        <m:action metadata=\"#olingo.odata.test1.BAETAllPrimRT\" "+
+        "          title=\"olingo.odata.test1.BAETAllPrimRT\" "+
+        "          target=\"ESAllPrim(0)/olingo.odata.test1.BAETAllPrimRT\" />\n" + 
         "        </a:entry>\n" +
         "      </a:feed>\n" +
         "    </m:inline>\n" +


[3/3] olingo-odata4 git commit: OLINGO-567: Support for odata.metadata=full

Posted by ra...@apache.org.
OLINGO-567: Support for odata.metadata=full


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

Branch: refs/heads/OLINGO-567-rareddy
Commit: eaceb01d1ae00f664cef6811f11a303f8771db8c
Parents: 2675f8f
Author: Ramesh Reddy <ra...@jboss.org>
Authored: Mon May 23 14:44:12 2016 -0500
Committer: Ramesh Reddy <ra...@jboss.org>
Committed: Thu Jun 2 12:19:55 2016 -0500

----------------------------------------------------------------------
 .../fit/tecsvc/client/BoundOpearionITCase.java  | 149 ++++++++
 .../tecsvc/client/EntityWithStreamITCase.java   | 112 ++++++
 .../fit/tecsvc/http/BasicStreamITCase.java      |   2 +-
 .../client/api/domain/ClientEntitySet.java      |  15 +
 .../olingo/client/api/domain/ClientLink.java    |  25 +-
 .../client/api/domain/ClientLinkType.java       |   9 +
 .../client/api/domain/ClientObjectFactory.java  |   6 +-
 .../client/api/domain/ClientProperty.java       |  17 +
 .../core/domain/ClientComplexValueImpl.java     |   1 +
 .../client/core/domain/ClientEntityImpl.java    |   1 +
 .../client/core/domain/ClientEntitySetImpl.java |  26 ++
 .../core/domain/ClientObjectFactoryImpl.java    |  18 +-
 .../client/core/domain/ClientPropertyImpl.java  |  27 +-
 .../core/serialization/AtomDeserializer.java    |   4 +-
 .../core/serialization/JsonDeserializer.java    |   1 +
 .../serialization/JsonEntityDeserializer.java   |  49 ++-
 .../JsonEntitySetDeserializer.java              |  16 +-
 .../serialization/JsonPropertyDeserializer.java |  15 +-
 .../core/serialization/ODataBinderImpl.java     |  26 +-
 .../apache/olingo/commons/api/Constants.java    |   4 +
 .../api/data/AbstractEntityCollection.java      |   3 +
 .../commons/api/data/EntityCollection.java      |  13 +-
 .../olingo/commons/api/data/Operation.java      |  20 +-
 .../olingo/commons/api/data/Property.java       |  13 +
 .../core/edm/primitivetype/EdmStream.java       |   7 +
 .../olingo/server/core/ServiceRequest.java      |   9 +-
 .../olingo/server/core/ContentNegotiator.java   |   1 +
 .../apache/olingo/server/core/ODataImpl.java    |   3 +-
 .../deserializer/xml/ODataXmlDeserializer.java  |   3 +-
 .../serializer/json/ODataJsonSerializer.java    | 179 +++++++--
 .../serializer/utils/ContentTypeHelper.java     |   5 +
 .../core/serializer/xml/ODataXmlSerializer.java |  18 +-
 .../server/core/ContentNegotiatorTest.java      |   1 -
 .../olingo/server/core/ODataImplTest.java       |   7 +-
 .../olingo/server/tecsvc/data/ActionData.java   |  14 +-
 .../olingo/server/tecsvc/data/DataCreator.java  | 232 ++++++++++--
 .../olingo/server/tecsvc/data/DataProvider.java |   6 +-
 .../olingo/server/tecsvc/data/FunctionData.java |   5 +
 .../processor/TechnicalEntityProcessor.java     |   7 +
 .../ExpandSystemQueryOptionHandler.java         |   2 +-
 .../server/tecsvc/provider/ActionProvider.java  |  22 +-
 .../tecsvc/provider/ContainerProvider.java      |   5 +
 .../tecsvc/provider/EntityTypeProvider.java     |  13 +-
 .../tecsvc/provider/FunctionProvider.java       |  86 ++++-
 .../tecsvc/provider/PropertyProvider.java       |   6 +
 .../json/ODataJsonSerializerTest.java           | 360 ++++++++++++++++++-
 .../serializer/xml/ODataXmlSerializerTest.java  | 188 +++++++++-
 47 files changed, 1628 insertions(+), 123 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/eaceb01d/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BoundOpearionITCase.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BoundOpearionITCase.java b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BoundOpearionITCase.java
new file mode 100644
index 0000000..a37ab49
--- /dev/null
+++ b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BoundOpearionITCase.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.fit.tecsvc.client;
+
+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.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.client.api.communication.request.retrieve.ODataEntitySetRequest;
+import org.apache.olingo.client.api.communication.request.retrieve.ODataPropertyRequest;
+import org.apache.olingo.client.api.communication.response.ODataRetrieveResponse;
+import org.apache.olingo.client.api.domain.ClientAnnotation;
+import org.apache.olingo.client.api.domain.ClientEntity;
+import org.apache.olingo.client.api.domain.ClientEntitySet;
+import org.apache.olingo.client.api.domain.ClientOperation;
+import org.apache.olingo.client.api.domain.ClientProperty;
+import org.apache.olingo.commons.api.format.ContentType;
+import org.apache.olingo.commons.api.http.HttpStatusCode;
+import org.junit.Test;
+import org.junit.runners.Parameterized;
+
+public class BoundOpearionITCase extends AbstractParamTecSvcITCase {
+  private static final ContentType CONTENT_TYPE_JSON_FULL_METADATA =
+      ContentType.create(ContentType.JSON, ContentType.PARAMETER_ODATA_METADATA, 
+          ContentType.VALUE_ODATA_METADATA_FULL);
+
+  @Parameterized.Parameters(name = "{0}")
+  public static List<ContentType[]> parameters() {
+    ContentType[] a = new ContentType[1];
+    a[0] = CONTENT_TYPE_JSON_FULL_METADATA;
+    ArrayList<ContentType[]> type = new ArrayList<ContentType[]>();
+    type.add(a);
+    return type;
+  }  
+  
+  @Test
+  public void readEntitySetOperation() {
+    ODataEntitySetRequest<ClientEntitySet> request = getClient().getRetrieveRequestFactory()
+        .getEntitySetRequest(getClient().newURIBuilder(SERVICE_URI)
+            .appendEntitySetSegment("ESAllPrim").build());    
+    assertNotNull(request);
+    setCookieHeader(request);
+
+    final ODataRetrieveResponse<ClientEntitySet> response = request.execute();
+    saveCookieHeader(response);
+    assertEquals(HttpStatusCode.OK.getStatusCode(), response.getStatusCode());
+    assertEquals("application/json; odata.metadata=full", response.getContentType());
+
+    final ClientEntitySet entitySet = response.getBody();
+    assertNotNull(entitySet);
+
+    assertNull(entitySet.getCount());
+    assertNull(entitySet.getNext());
+    assertEquals(Collections.<ClientAnnotation> emptyList(), entitySet.getAnnotations());
+    assertNull(entitySet.getDeltaLink());
+
+    List<ClientOperation> ecOperations = entitySet.getOperations();
+    assertNotNull(ecOperations);
+    assertEquals(4, ecOperations.size());
+    
+    assertEquals("#olingo.odata.test1.BAESAllPrimRTETAllPrim", ecOperations.get(0).getMetadataAnchor());
+    assertEquals("olingo.odata.test1.BAESAllPrimRTETAllPrim", ecOperations.get(0).getTitle());
+    assertEquals("/ESAllPrim/olingo.odata.test1.BAESAllPrimRTETAllPrim", 
+        ecOperations.get(0).getTarget().toASCIIString());    
+    
+    assertEquals("#olingo.odata.test1.BAESAllPrimRT", ecOperations.get(1).getMetadataAnchor());
+    assertEquals("olingo.odata.test1.BAESAllPrimRT", ecOperations.get(1).getTitle());
+    assertEquals("/ESAllPrim/olingo.odata.test1.BAESAllPrimRT", 
+        ecOperations.get(1).getTarget().toASCIIString());
+    
+    
+    assertEquals("#olingo.odata.test1.BFNESAllPrimRTCTAllPrim", ecOperations.get(2).getMetadataAnchor());
+    assertEquals("olingo.odata.test1.BFNESAllPrimRTCTAllPrim", ecOperations.get(2).getTitle());
+    assertEquals("/ESAllPrim/olingo.odata.test1.BFNESAllPrimRTCTAllPrim", 
+        ecOperations.get(2).getTarget().toASCIIString());
+    
+    assertEquals("#olingo.odata.test1.BFNESAllPrimRTCTAllPrim(Param2)", ecOperations.get(3).getMetadataAnchor());
+    assertEquals("olingo.odata.test1.BFNESAllPrimRTCTAllPrim", ecOperations.get(3).getTitle());
+    assertEquals("/ESAllPrim/olingo.odata.test1.BFNESAllPrimRTCTAllPrim(Param2=@Param2)", 
+        ecOperations.get(3).getTarget().toASCIIString());
+    
+    final List<ClientEntity> entities = entitySet.getEntities();
+    assertNotNull(entities);
+    assertEquals(3, entities.size());
+    
+    ClientEntity entity = entities.get(0);
+    assertNotNull(entity);
+    List<ClientOperation> operations = entity.getOperations();
+    assertNotNull(operations);
+    assertEquals(1, operations.size());
+    
+    assertEquals("#olingo.odata.test1.BAETAllPrimRT", operations.get(0).getMetadataAnchor());
+    assertEquals("olingo.odata.test1.BAETAllPrimRT", operations.get(0).getTitle());
+    assertEquals("/ESAllPrim(32767)/olingo.odata.test1.BAETAllPrimRT", 
+        operations.get(0).getTarget().toASCIIString());              
+  } 
+  
+  @Test
+  public void readComplexPropertyOperation() {
+    ODataPropertyRequest<ClientProperty> request = getClient().getRetrieveRequestFactory()
+        .getPropertyRequest(getClient().newURIBuilder(SERVICE_URI)
+            .appendEntitySetSegment("ESCompAllPrim")
+            .appendKeySegment(32767)
+            .appendPropertySegment("PropertyComp")
+            .build());    
+    assertNotNull(request);
+    setCookieHeader(request);
+
+    final ODataRetrieveResponse<ClientProperty> response = request.execute();
+    saveCookieHeader(response);
+    assertEquals(HttpStatusCode.OK.getStatusCode(), response.getStatusCode());
+    assertEquals("application/json; odata.metadata=full", response.getContentType());
+
+    final ClientProperty property = response.getBody();
+    assertNotNull(property);
+    
+    List<ClientOperation> operations = property.getOperations();
+    assertNotNull(operations);
+    
+    assertEquals(1, operations.size());
+    
+    assertEquals("#olingo.odata.test1.BFCColCTAllPrimRTESAllPrim", operations.get(0).getMetadataAnchor());
+    assertEquals("olingo.odata.test1.BFCColCTAllPrimRTESAllPrim", operations.get(0).getTitle());
+    assertEquals("PropertyComp/olingo.odata.test1.BFCColCTAllPrimRTESAllPrim", 
+        operations.get(0).getTarget().toASCIIString());                  
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/eaceb01d/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/EntityWithStreamITCase.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/EntityWithStreamITCase.java b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/EntityWithStreamITCase.java
new file mode 100644
index 0000000..a99f02c
--- /dev/null
+++ b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/EntityWithStreamITCase.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.fit.tecsvc.client;
+
+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.Collections;
+import java.util.List;
+
+import org.apache.olingo.client.api.communication.request.retrieve.ODataEntitySetRequest;
+import org.apache.olingo.client.api.communication.response.ODataRetrieveResponse;
+import org.apache.olingo.client.api.domain.ClientAnnotation;
+import org.apache.olingo.client.api.domain.ClientEntity;
+import org.apache.olingo.client.api.domain.ClientEntitySet;
+import org.apache.olingo.client.api.domain.ClientLink;
+import org.apache.olingo.client.api.domain.ClientLinkType;
+import org.apache.olingo.client.api.domain.ClientProperty;
+import org.apache.olingo.commons.api.Constants;
+import org.apache.olingo.commons.api.format.ContentType;
+import org.apache.olingo.commons.api.http.HttpStatusCode;
+import org.junit.Test;
+import org.junit.runners.Parameterized;
+
+public class EntityWithStreamITCase extends AbstractParamTecSvcITCase {
+  private static final ContentType CONTENT_TYPE_JSON_FULL_METADATA =
+      ContentType.create(ContentType.JSON, ContentType.PARAMETER_ODATA_METADATA, 
+          ContentType.VALUE_ODATA_METADATA_FULL);
+  private static final String PROPERTY_INT16 = "PropertyInt16";
+
+  @Parameterized.Parameters(name = "{0}")
+  public static List<ContentType[]> parameters() {
+    ContentType[] a = new ContentType[1];
+    a[0] = CONTENT_TYPE_JSON_FULL_METADATA;
+    ArrayList<ContentType[]> type = new ArrayList<ContentType[]>();
+    type.add(a);
+    return type;
+  }  
+  
+  @Test
+  public void readEntitySetWithStreamProperty() {
+    ODataEntitySetRequest<ClientEntitySet> request = getClient().getRetrieveRequestFactory()
+        .getEntitySetRequest(getClient().newURIBuilder(SERVICE_URI)
+            .appendEntitySetSegment("ESWithStream").build());    
+    assertNotNull(request);
+    setCookieHeader(request);
+
+    final ODataRetrieveResponse<ClientEntitySet> response = request.execute();
+    saveCookieHeader(response);
+    assertEquals(HttpStatusCode.OK.getStatusCode(), response.getStatusCode());
+    assertEquals("application/json; odata.metadata=full", response.getContentType());
+
+    final ClientEntitySet entitySet = response.getBody();
+    assertNotNull(entitySet);
+
+    assertNull(entitySet.getCount());
+    assertNull(entitySet.getNext());
+    assertEquals(Collections.<ClientAnnotation> emptyList(), entitySet.getAnnotations());
+    assertNull(entitySet.getDeltaLink());
+
+    final List<ClientEntity> entities = entitySet.getEntities();
+    assertNotNull(entities);
+    assertEquals(2, entities.size());
+    
+    ClientEntity entity = entities.get(0);
+    assertNotNull(entity);
+    ClientProperty property = entity.getProperty(PROPERTY_INT16);
+    assertNotNull(property);
+    assertNotNull(property.getPrimitiveValue());
+    assertShortOrInt(Short.MAX_VALUE, property.getPrimitiveValue().toValue());
+    
+    ClientLink link = entity.getMediaEditLinks().get(0);
+    assertNotNull(link);
+    
+    assertEquals("/readLink", link.getLink().toASCIIString());
+    assertEquals(ClientLinkType.MEDIA_READ, link.getType());
+    
+    entity = entities.get(1);
+    assertNotNull(entity);
+    property = entity.getProperty(PROPERTY_INT16);
+    assertNotNull(property);
+    assertNotNull(property.getPrimitiveValue());
+    assertShortOrInt(7, property.getPrimitiveValue().toValue());
+    
+    assertEquals(1, entity.getMediaEditLinks().size());
+    
+    link = entity.getMediaEditLinks().get(0);
+    assertNotNull(link);
+    assertEquals("http://mediaserver:1234/editLink", link.getLink().toASCIIString());
+    assertEquals(ClientLinkType.fromString(Constants.NS_MEDIA_EDIT_LINK_REL, "image/jpeg").name(), 
+        link.getType().name());
+    assertEquals("eTag", link.getMediaETag());    
+  } 
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/eaceb01d/fit/src/test/java/org/apache/olingo/fit/tecsvc/http/BasicStreamITCase.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/tecsvc/http/BasicStreamITCase.java b/fit/src/test/java/org/apache/olingo/fit/tecsvc/http/BasicStreamITCase.java
index 566cb39..33eb4f5 100644
--- a/fit/src/test/java/org/apache/olingo/fit/tecsvc/http/BasicStreamITCase.java
+++ b/fit/src/test/java/org/apache/olingo/fit/tecsvc/http/BasicStreamITCase.java
@@ -70,7 +70,7 @@ public class BasicStreamITCase extends AbstractBaseTestITCase {
     assertEquals(ContentType.APPLICATION_XML, ContentType.create(connection.getHeaderField(HttpHeader.CONTENT_TYPE)));
 
     final String content = IOUtils.toString(connection.getInputStream());
-
+System.out.println(content);
     assertTrue(content.contains("<m:element>Streamed-Employee1@company.example</m:element>" +
             "<m:element>Streamed-Employee2@company.example</m:element>" +
             "<m:element>Streamed-Employee3@company.example</m:element>"));

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/eaceb01d/lib/client-api/src/main/java/org/apache/olingo/client/api/domain/ClientEntitySet.java
----------------------------------------------------------------------
diff --git a/lib/client-api/src/main/java/org/apache/olingo/client/api/domain/ClientEntitySet.java b/lib/client-api/src/main/java/org/apache/olingo/client/api/domain/ClientEntitySet.java
index 6b5f1f1..e1664be 100644
--- a/lib/client-api/src/main/java/org/apache/olingo/client/api/domain/ClientEntitySet.java
+++ b/lib/client-api/src/main/java/org/apache/olingo/client/api/domain/ClientEntitySet.java
@@ -68,4 +68,19 @@ public interface ClientEntitySet extends ClientInvokeResult, ClientAnnotatable {
    * @param deltaLink delta link.
    */
   void setDeltaLink(URI deltaLink);
+  
+  /**
+   * Searches for operation with given title.
+   * 
+   * @param title operation to look for
+   * @return operation if found with given title, <tt>null</tt> otherwise
+   */
+  ClientOperation getOperation(String title);
+
+  /**
+   * Gets operations.
+   * 
+   * @return operations.
+   */
+  List<ClientOperation> getOperations();  
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/eaceb01d/lib/client-api/src/main/java/org/apache/olingo/client/api/domain/ClientLink.java
----------------------------------------------------------------------
diff --git a/lib/client-api/src/main/java/org/apache/olingo/client/api/domain/ClientLink.java b/lib/client-api/src/main/java/org/apache/olingo/client/api/domain/ClientLink.java
index 5307165..35f89fb 100644
--- a/lib/client-api/src/main/java/org/apache/olingo/client/api/domain/ClientLink.java
+++ b/lib/client-api/src/main/java/org/apache/olingo/client/api/domain/ClientLink.java
@@ -36,7 +36,9 @@ public class ClientLink extends ClientItem implements ClientAnnotatable {
     private ClientLinkType type;
 
     private String title;
-
+    
+    private String mediaETag;
+    
     public Builder setURI(final URI uri) {
       this.uri = uri;
       return this;
@@ -57,8 +59,13 @@ public class ClientLink extends ClientItem implements ClientAnnotatable {
       return this;
     }
 
+    public Builder setEtag(final String eTag) {
+      this.mediaETag= eTag;
+      return this;
+    }
+
     public ClientLink build() {
-      return new ClientLink(uri, type, title);
+      return new ClientLink(uri, type, title, mediaETag);
     }
   }
 
@@ -110,10 +117,15 @@ public class ClientLink extends ClientItem implements ClientAnnotatable {
    * @param title title.
    */
   public ClientLink(final URI uri, final ClientLinkType type, final String title) {
+    this(uri, type, title, null);
+  }
+  
+  public ClientLink(final URI uri, final ClientLinkType type, final String title, final String eTag) {
     super(title);
 
     this.type = type;
     setLink(uri);
+    this.mediaETag = eTag;
 
     switch (this.type) {
     case ASSOCIATION:
@@ -126,12 +138,19 @@ public class ClientLink extends ClientItem implements ClientAnnotatable {
       break;
 
     case MEDIA_EDIT:
+      rel = Constants.NS_MEDIA_EDIT_LINK_REL + title;
+      break;
+
+    case MEDIA_READ:
+      rel = Constants.NS_MEDIA_READ_LINK_REL + title;
+      break;
+      
     default:
       rel = Constants.NS_MEDIA_EDIT_LINK_REL + title;
       break;
     }
   }
-
+  
   /**
    * Constructor.
    * 

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/eaceb01d/lib/client-api/src/main/java/org/apache/olingo/client/api/domain/ClientLinkType.java
----------------------------------------------------------------------
diff --git a/lib/client-api/src/main/java/org/apache/olingo/client/api/domain/ClientLinkType.java b/lib/client-api/src/main/java/org/apache/olingo/client/api/domain/ClientLinkType.java
index 2b89b95..ff1f6f4 100644
--- a/lib/client-api/src/main/java/org/apache/olingo/client/api/domain/ClientLinkType.java
+++ b/lib/client-api/src/main/java/org/apache/olingo/client/api/domain/ClientLinkType.java
@@ -42,6 +42,11 @@ public enum ClientLinkType {
    * Media-edit link.
    */
   MEDIA_EDIT("*/*"),
+  
+  /**
+   * Media-read link
+   */
+  MEDIA_READ("*/*"),
 
   /**
    * Entity binding link.
@@ -80,6 +85,10 @@ public enum ClientLinkType {
     if (rel != null && rel.startsWith(Constants.NS_MEDIA_EDIT_LINK_REL)) {
       return MEDIA_EDIT.setType(type == null || type.isEmpty() ? "*/*" : type);
     }
+    
+    if (rel != null && rel.startsWith(Constants.NS_MEDIA_READ_LINK_REL)) {
+      return MEDIA_READ.setType(type == null || type.isEmpty() ? "*/*" : type);
+    }
 
     if (ClientLinkType.ENTITY_NAVIGATION.type.equals(type)) {
       return ENTITY_NAVIGATION;

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/eaceb01d/lib/client-api/src/main/java/org/apache/olingo/client/api/domain/ClientObjectFactory.java
----------------------------------------------------------------------
diff --git a/lib/client-api/src/main/java/org/apache/olingo/client/api/domain/ClientObjectFactory.java b/lib/client-api/src/main/java/org/apache/olingo/client/api/domain/ClientObjectFactory.java
index 5bf1e08..774bd94 100644
--- a/lib/client-api/src/main/java/org/apache/olingo/client/api/domain/ClientObjectFactory.java
+++ b/lib/client-api/src/main/java/org/apache/olingo/client/api/domain/ClientObjectFactory.java
@@ -105,8 +105,10 @@ public interface ClientObjectFactory {
 
   ClientLink newAssociationLink(String name, URI link);
 
-  ClientLink newMediaEditLink(String name, URI link);
-
+  ClientLink newMediaEditLink(String name, URI link, String type, String eTag);
+  
+  ClientLink newMediaReadLink(String name, URI link, String type, String eTag);
+  
   ClientPrimitiveValue.Builder newPrimitiveValueBuilder();
 
   ClientEnumValue newEnumValue(String typeName, String value);

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/eaceb01d/lib/client-api/src/main/java/org/apache/olingo/client/api/domain/ClientProperty.java
----------------------------------------------------------------------
diff --git a/lib/client-api/src/main/java/org/apache/olingo/client/api/domain/ClientProperty.java b/lib/client-api/src/main/java/org/apache/olingo/client/api/domain/ClientProperty.java
index 2e5dde8..8e14c94 100644
--- a/lib/client-api/src/main/java/org/apache/olingo/client/api/domain/ClientProperty.java
+++ b/lib/client-api/src/main/java/org/apache/olingo/client/api/domain/ClientProperty.java
@@ -18,6 +18,8 @@
  */
 package org.apache.olingo.client.api.domain;
 
+import java.util.List;
+
 /**
  * OData entity property.
  */
@@ -29,4 +31,19 @@ public interface ClientProperty extends ClientInvokeResult, ClientAnnotatable, C
    * @return property name.
    */
   String getName();
+  
+  /**
+   * Searches for operation with given title.
+   * 
+   * @param title operation to look for
+   * @return operation if found with given title, <tt>null</tt> otherwise
+   */
+  ClientOperation getOperation(String title);
+
+  /**
+   * Gets operations.
+   * 
+   * @return operations.
+   */
+  List<ClientOperation> getOperations();  
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/eaceb01d/lib/client-core/src/main/java/org/apache/olingo/client/core/domain/ClientComplexValueImpl.java
----------------------------------------------------------------------
diff --git a/lib/client-core/src/main/java/org/apache/olingo/client/core/domain/ClientComplexValueImpl.java b/lib/client-core/src/main/java/org/apache/olingo/client/core/domain/ClientComplexValueImpl.java
index 9cd083e..1338a92 100644
--- a/lib/client-core/src/main/java/org/apache/olingo/client/core/domain/ClientComplexValueImpl.java
+++ b/lib/client-core/src/main/java/org/apache/olingo/client/core/domain/ClientComplexValueImpl.java
@@ -89,6 +89,7 @@ public class ClientComplexValueImpl extends AbstractClientValue implements Clien
       break;
 
     case MEDIA_EDIT:
+    case MEDIA_READ:
       throw new IllegalArgumentException("Complex values cannot have media links!");
 
     default:

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/eaceb01d/lib/client-core/src/main/java/org/apache/olingo/client/core/domain/ClientEntityImpl.java
----------------------------------------------------------------------
diff --git a/lib/client-core/src/main/java/org/apache/olingo/client/core/domain/ClientEntityImpl.java b/lib/client-core/src/main/java/org/apache/olingo/client/core/domain/ClientEntityImpl.java
index 4426e03..76ee05f 100644
--- a/lib/client-core/src/main/java/org/apache/olingo/client/core/domain/ClientEntityImpl.java
+++ b/lib/client-core/src/main/java/org/apache/olingo/client/core/domain/ClientEntityImpl.java
@@ -160,6 +160,7 @@ public class ClientEntityImpl extends AbstractClientPayload implements ClientEnt
         break;
 
       case MEDIA_EDIT:
+      case MEDIA_READ:
         result = mediaEditLinks.contains(link) ? false : mediaEditLinks.add(link);
         break;
 

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/eaceb01d/lib/client-core/src/main/java/org/apache/olingo/client/core/domain/ClientEntitySetImpl.java
----------------------------------------------------------------------
diff --git a/lib/client-core/src/main/java/org/apache/olingo/client/core/domain/ClientEntitySetImpl.java b/lib/client-core/src/main/java/org/apache/olingo/client/core/domain/ClientEntitySetImpl.java
index 21e13b4..a979196 100644
--- a/lib/client-core/src/main/java/org/apache/olingo/client/core/domain/ClientEntitySetImpl.java
+++ b/lib/client-core/src/main/java/org/apache/olingo/client/core/domain/ClientEntitySetImpl.java
@@ -26,6 +26,7 @@ import org.apache.olingo.client.api.domain.AbstractClientPayload;
 import org.apache.olingo.client.api.domain.ClientAnnotation;
 import org.apache.olingo.client.api.domain.ClientEntity;
 import org.apache.olingo.client.api.domain.ClientEntitySet;
+import org.apache.olingo.client.api.domain.ClientOperation;
 
 public class ClientEntitySetImpl extends AbstractClientPayload implements ClientEntitySet {
 
@@ -46,6 +47,8 @@ public class ClientEntitySetImpl extends AbstractClientPayload implements Client
   private final List<ClientEntity> entities = new ArrayList<ClientEntity>();
 
   private final List<ClientAnnotation> annotations = new ArrayList<ClientAnnotation>();
+  
+  private final List<ClientOperation> operations = new ArrayList<ClientOperation>();
 
   public ClientEntitySetImpl() {
     super(null);
@@ -93,6 +96,29 @@ public class ClientEntitySetImpl extends AbstractClientPayload implements Client
   }
 
   @Override
+  public ClientOperation getOperation(final String title) {
+    ClientOperation result = null;
+    for (ClientOperation operation : operations) {
+      if (title.equals(operation.getTitle())) {
+        result = operation;
+        break;
+      }
+    }
+
+    return result;
+  }
+
+  /**
+   * Gets operations.
+   *
+   * @return operations.
+   */
+  @Override
+  public List<ClientOperation> getOperations() {
+    return operations;
+  }
+  
+  @Override
   public int hashCode() {
     final int prime = 31;
     int result = super.hashCode();

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/eaceb01d/lib/client-core/src/main/java/org/apache/olingo/client/core/domain/ClientObjectFactoryImpl.java
----------------------------------------------------------------------
diff --git a/lib/client-core/src/main/java/org/apache/olingo/client/core/domain/ClientObjectFactoryImpl.java b/lib/client-core/src/main/java/org/apache/olingo/client/core/domain/ClientObjectFactoryImpl.java
index 7bca6c3..5914cee 100644
--- a/lib/client-core/src/main/java/org/apache/olingo/client/core/domain/ClientObjectFactoryImpl.java
+++ b/lib/client-core/src/main/java/org/apache/olingo/client/core/domain/ClientObjectFactoryImpl.java
@@ -35,6 +35,7 @@ import org.apache.olingo.client.api.domain.ClientPrimitiveValue;
 import org.apache.olingo.client.api.domain.ClientProperty;
 import org.apache.olingo.client.api.domain.ClientSingleton;
 import org.apache.olingo.client.api.domain.ClientValue;
+import org.apache.olingo.commons.api.Constants;
 import org.apache.olingo.commons.api.edm.FullQualifiedName;
 
 public class ClientObjectFactoryImpl implements ClientObjectFactory {
@@ -95,11 +96,20 @@ public class ClientObjectFactoryImpl implements ClientObjectFactory {
   }
 
   @Override
-  public ClientLink newMediaEditLink(final String name, final URI link) {
-    return new ClientLink.Builder().setURI(link).
-        setType(ClientLinkType.MEDIA_EDIT).setTitle(name).build();
+  public ClientLink newMediaEditLink(String name, URI link, String type, String eTag) {
+    return new ClientLink.Builder().setURI(link).setEtag(eTag).
+        setType(ClientLinkType.fromString(Constants.NS_MEDIA_EDIT_LINK_REL,
+            type == null ? Constants.MEDIA_EDIT_LINK_TYPE : type))
+        .setTitle(name).build();    
   }
-
+  
+  public ClientLink newMediaReadLink(String name, URI link, String type, String eTag) {
+    return new ClientLink.Builder().setURI(link).setEtag(eTag).
+        setType(ClientLinkType.fromString(Constants.NS_MEDIA_READ_LINK_REL,
+            type == null ? Constants.MEDIA_EDIT_LINK_TYPE : type))
+        .setTitle(name).build();    
+  }
+  
   @Override
   public ClientPrimitiveValue.Builder newPrimitiveValueBuilder() {
     return new ClientPrimitiveValueImpl.BuilderImpl();

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/eaceb01d/lib/client-core/src/main/java/org/apache/olingo/client/core/domain/ClientPropertyImpl.java
----------------------------------------------------------------------
diff --git a/lib/client-core/src/main/java/org/apache/olingo/client/core/domain/ClientPropertyImpl.java b/lib/client-core/src/main/java/org/apache/olingo/client/core/domain/ClientPropertyImpl.java
index 8c8c3ee..d9aa892 100644
--- a/lib/client-core/src/main/java/org/apache/olingo/client/core/domain/ClientPropertyImpl.java
+++ b/lib/client-core/src/main/java/org/apache/olingo/client/core/domain/ClientPropertyImpl.java
@@ -22,6 +22,7 @@ import java.util.ArrayList;
 import java.util.List;
 
 import org.apache.olingo.client.api.domain.ClientAnnotation;
+import org.apache.olingo.client.api.domain.ClientOperation;
 import org.apache.olingo.client.api.domain.ClientProperty;
 import org.apache.olingo.client.api.domain.ClientValue;
 
@@ -29,7 +30,8 @@ public final class ClientPropertyImpl extends ClientValuableImpl implements Clie
 
   private final List<ClientAnnotation> annotations = new ArrayList<ClientAnnotation>();
   private final String name;
-
+  private final List<ClientOperation> operations = new ArrayList<ClientOperation>();
+  
   public ClientPropertyImpl(final String name, final ClientValue value) {
     super(value);
     this.name = name;
@@ -45,6 +47,29 @@ public final class ClientPropertyImpl extends ClientValuableImpl implements Clie
     return name;
   }
 
+  @Override
+  public ClientOperation getOperation(final String title) {
+    ClientOperation result = null;
+    for (ClientOperation operation : operations) {
+      if (title.equals(operation.getTitle())) {
+        result = operation;
+        break;
+      }
+    }
+
+    return result;
+  }
+
+  /**
+   * Gets operations.
+   *
+   * @return operations.
+   */
+  @Override
+  public List<ClientOperation> getOperations() {
+    return operations;
+  }
+  
   /**
    * Checks if has null value.
    *

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/eaceb01d/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/AtomDeserializer.java
----------------------------------------------------------------------
diff --git a/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/AtomDeserializer.java b/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/AtomDeserializer.java
index 5c3b59e..037ebb5 100644
--- a/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/AtomDeserializer.java
+++ b/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/AtomDeserializer.java
@@ -640,8 +640,8 @@ public class AtomDeserializer extends AbstractAtomDealer implements ODataDeseria
               inline(reader, event.asStartElement(), link);
             } else if (link.getRel().startsWith(Constants.NS_ASSOCIATION_LINK_REL)) {
               entity.getAssociationLinks().add(link);
-            } else if (link.getRel().startsWith(Constants.NS_MEDIA_EDIT_LINK_REL)) {
-
+            } else if (link.getRel().startsWith(Constants.NS_MEDIA_EDIT_LINK_REL) ||
+                link.getRel().startsWith(Constants.NS_MEDIA_READ_LINK_REL)) {
               final Attribute metag = event.asStartElement().getAttributeByName(etagQName);
               if (metag != null) {
                 link.setMediaETag(metag.getValue());

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/eaceb01d/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/JsonDeserializer.java
----------------------------------------------------------------------
diff --git a/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/JsonDeserializer.java b/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/JsonDeserializer.java
index 3691d8b..8775f17 100644
--- a/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/JsonDeserializer.java
+++ b/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/JsonDeserializer.java
@@ -30,6 +30,7 @@ import java.util.Set;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
+import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.olingo.client.api.data.ResWrap;
 import org.apache.olingo.client.api.serialization.ODataDeserializer;

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/eaceb01d/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/JsonEntityDeserializer.java
----------------------------------------------------------------------
diff --git a/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/JsonEntityDeserializer.java b/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/JsonEntityDeserializer.java
index 53de9cb..53a0cab 100644
--- a/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/JsonEntityDeserializer.java
+++ b/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/JsonEntityDeserializer.java
@@ -148,29 +148,41 @@ public class JsonEntityDeserializer extends JsonDeserializer {
       final Matcher customAnnotation = CUSTOM_ANNOTATION.matcher(field.getKey());
 
       links(field, entity, toRemove, tree, parser.getCodec());
-      if (field.getKey().endsWith(getJSONAnnotation(Constants.JSON_MEDIA_EDIT_LINK))) {
+      if (field.getKey().endsWith(getJSONAnnotation(Constants.JSON_MEDIA_READ_LINK))) {
         final Link link = new Link();
         link.setTitle(getTitle(field));
-        link.setRel(Constants.NS_MEDIA_EDIT_LINK_REL + getTitle(field));
-        link.setHref(field.getValue().textValue());
+        link.setRel(Constants.NS_MEDIA_READ_LINK_REL + getTitle(field));
         link.setType(Constants.MEDIA_EDIT_LINK_TYPE);
+        link.setHref(field.getValue().textValue());
         entity.getMediaEditLinks().add(link);
-
+        
         if (tree.has(link.getTitle() + getJSONAnnotation(Constants.JSON_MEDIA_ETAG))) {
           link.setMediaETag(tree.get(link.getTitle() + getJSONAnnotation(Constants.JSON_MEDIA_ETAG)).asText());
           toRemove.add(link.getTitle() + getJSONAnnotation(Constants.JSON_MEDIA_ETAG));
         }
 
+        if (tree.has(link.getTitle() + getJSONAnnotation(Constants.JSON_MEDIA_CONTENT_TYPE))) {
+          link.setType(tree.get(link.getTitle() + getJSONAnnotation(Constants.JSON_MEDIA_CONTENT_TYPE)).asText());
+          toRemove.add(link.getTitle() + getJSONAnnotation(Constants.JSON_MEDIA_CONTENT_TYPE));
+        }        
+        
+        toRemove.add(field.getKey());
+        toRemove.add(setInline(field.getKey(), getJSONAnnotation(Constants.JSON_MEDIA_READ_LINK), tree, parser
+            .getCodec(), link));
+      } else if (field.getKey().endsWith(getJSONAnnotation(Constants.JSON_MEDIA_EDIT_LINK))) {
+        final Link link = getOrCreateMediaLink(entity, getTitle(field));
+        link.setRel(Constants.NS_MEDIA_EDIT_LINK_REL + getTitle(field));
+        link.setHref(field.getValue().textValue());
         toRemove.add(field.getKey());
         toRemove.add(setInline(field.getKey(), getJSONAnnotation(Constants.JSON_MEDIA_EDIT_LINK), tree, parser
             .getCodec(), link));
-      } else if (field.getKey().endsWith(getJSONAnnotation(Constants.JSON_MEDIA_CONTENT_TYPE))) {
-        final String linkTitle = getTitle(field);
-        for (Link link : entity.getMediaEditLinks()) {
-          if (linkTitle.equals(link.getTitle())) {
-            link.setType(field.getValue().asText());
-          }
-        }
+      } else if (field.getKey().endsWith(getJSONAnnotation(Constants.JSON_MEDIA_CONTENT_TYPE))) {        
+        final Link link = getOrCreateMediaLink(entity, getTitle(field));
+        link.setType(field.getValue().asText());
+        toRemove.add(field.getKey());
+      } else if (field.getKey().endsWith(getJSONAnnotation(Constants.JSON_MEDIA_ETAG))) {        
+        final Link link = getOrCreateMediaLink(entity, getTitle(field));
+        link.setMediaETag(field.getValue().asText());
         toRemove.add(field.getKey());
       } else if (field.getKey().charAt(0) == '#') {
         final Operation operation = new Operation();
@@ -226,4 +238,19 @@ public class JsonEntityDeserializer extends JsonDeserializer {
 
     return new ResWrap<Entity>(contextURL, metadataETag, entity);
   }
+  
+  private Link getOrCreateMediaLink(final Entity entity, final String name) {
+    final String rel = Constants.NS_MEDIA_EDIT_LINK_REL + name;
+    for (Link link : entity.getMediaEditLinks()) {
+      if (link.getRel().equals(rel)) {        
+        return link;
+      }
+    }
+    final Link link = new Link();
+    link.setTitle(name);
+    link.setRel(rel);
+    link.setType(Constants.MEDIA_EDIT_LINK_TYPE);
+    entity.getMediaEditLinks().add(link);
+    return link;
+  }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/eaceb01d/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/JsonEntitySetDeserializer.java
----------------------------------------------------------------------
diff --git a/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/JsonEntitySetDeserializer.java b/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/JsonEntitySetDeserializer.java
index 401b31a..d54b98b 100644
--- a/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/JsonEntitySetDeserializer.java
+++ b/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/JsonEntitySetDeserializer.java
@@ -20,14 +20,17 @@ package org.apache.olingo.client.core.serialization;
 
 import java.io.IOException;
 import java.net.URI;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Map;
+import java.util.Set;
 
 import org.apache.commons.lang3.StringUtils;
 import org.apache.olingo.client.api.data.ResWrap;
 import org.apache.olingo.commons.api.Constants;
 import org.apache.olingo.commons.api.data.Annotation;
 import org.apache.olingo.commons.api.data.EntityCollection;
+import org.apache.olingo.commons.api.data.Operation;
 import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
 
 import com.fasterxml.jackson.core.JsonParser;
@@ -98,7 +101,7 @@ public class JsonEntitySetDeserializer extends JsonDeserializer {
       }
       tree.remove(Constants.VALUE);
     }
-
+    final Set<String> toRemove = new HashSet<String>();
     // any remaining entry is supposed to be an annotation or is ignored
     for (final Iterator<Map.Entry<String, JsonNode>> itor = tree.fields(); itor.hasNext();) {
       final Map.Entry<String, JsonNode> field = itor.next();
@@ -112,9 +115,18 @@ public class JsonEntitySetDeserializer extends JsonDeserializer {
           throw new IOException(e);
         }
         entitySet.getAnnotations().add(annotation);
+      } else if (field.getKey().charAt(0) == '#') {
+        final Operation operation = new Operation();
+        operation.setMetadataAnchor(field.getKey());
+
+        final ObjectNode opNode = (ObjectNode) tree.get(field.getKey());
+        operation.setTitle(opNode.get(Constants.ATTR_TITLE).asText());
+        operation.setTarget(URI.create(opNode.get(Constants.ATTR_TARGET).asText()));
+        entitySet.getOperations().add(operation);
+        toRemove.add(field.getKey());
       }
     }
-
+    tree.remove(toRemove);
     return new ResWrap<EntityCollection>(contextURL, metadataETag, entitySet);
   }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/eaceb01d/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/JsonPropertyDeserializer.java
----------------------------------------------------------------------
diff --git a/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/JsonPropertyDeserializer.java b/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/JsonPropertyDeserializer.java
index cb1c65a..af21df7 100644
--- a/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/JsonPropertyDeserializer.java
+++ b/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/JsonPropertyDeserializer.java
@@ -20,13 +20,16 @@ package org.apache.olingo.client.core.serialization;
 
 import java.io.IOException;
 import java.net.URI;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Map;
+import java.util.Set;
 
 import org.apache.commons.lang3.StringUtils;
 import org.apache.olingo.client.api.data.ResWrap;
 import org.apache.olingo.commons.api.Constants;
 import org.apache.olingo.commons.api.data.Annotation;
+import org.apache.olingo.commons.api.data.Operation;
 import org.apache.olingo.commons.api.data.Property;
 import org.apache.olingo.commons.api.data.ValueType;
 import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
@@ -93,6 +96,7 @@ public class JsonPropertyDeserializer extends JsonDeserializer {
       tree.remove(Constants.VALUE);
     }
 
+    Set<String> toRemove = new HashSet<String>();
     // any remaining entry is supposed to be an annotation or is ignored
     for (final Iterator<Map.Entry<String, JsonNode>> itor = tree.fields(); itor.hasNext();) {
       final Map.Entry<String, JsonNode> field = itor.next();
@@ -106,9 +110,18 @@ public class JsonPropertyDeserializer extends JsonDeserializer {
           throw new IOException(e);
         }
         property.getAnnotations().add(annotation);
+      } else if (field.getKey().charAt(0) == '#') {
+        final Operation operation = new Operation();
+        operation.setMetadataAnchor(field.getKey());
+
+        final ObjectNode opNode = (ObjectNode) tree.get(field.getKey());
+        operation.setTitle(opNode.get(Constants.ATTR_TITLE).asText());
+        operation.setTarget(URI.create(opNode.get(Constants.ATTR_TARGET).asText()));
+        property.getOperations().add(operation);
+        toRemove.add(field.getKey());
       }
     }
-
+    tree.remove(toRemove);
     return new ResWrap<Property>(contextURL, metadataETag, property);
   }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/eaceb01d/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/ODataBinderImpl.java
----------------------------------------------------------------------
diff --git a/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/ODataBinderImpl.java b/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/ODataBinderImpl.java
index a67de48..1059c58 100644
--- a/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/ODataBinderImpl.java
+++ b/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/ODataBinderImpl.java
@@ -414,6 +414,14 @@ public class ODataBinderImpl implements ODataBinder {
     if (resource.getPayload().getCount() != null) {
       entitySet.setCount(resource.getPayload().getCount());
     }
+    
+    for (Operation op : resource.getPayload().getOperations()) {
+      ClientOperation operation = new ClientOperation();
+      operation.setTarget(URIUtils.getURI(base, op.getTarget()));
+      operation.setTitle(op.getTitle());
+      operation.setMetadataAnchor(op.getMetadataAnchor());
+      entitySet.getOperations().add(operation);
+    }    
 
     for (Entity entityResource : resource.getPayload().getEntities()) {
       add(entitySet, getODataEntity(
@@ -660,8 +668,13 @@ public class ODataBinderImpl implements ODataBinder {
     odataNavigationLinks(edmType, resource.getPayload(), entity, resource.getMetadataETag(), base);
 
     for (Link link : resource.getPayload().getMediaEditLinks()) {
-      entity.addLink(client.getObjectFactory().
-          newMediaEditLink(link.getTitle(), URIUtils.getURI(base, link.getHref())));
+      if (link.getRel().startsWith(Constants.NS_MEDIA_READ_LINK_REL)) {
+        entity.addLink(client.getObjectFactory().newMediaReadLink(link.getTitle(), 
+            URIUtils.getURI(base, link.getHref()), link.getType(), link.getMediaETag()));
+      } else {
+        entity.addLink(client.getObjectFactory().newMediaEditLink(link.getTitle(), 
+            URIUtils.getURI(base, link.getHref()), link.getType(), link.getMediaETag()));        
+      }
     }
 
     for (Operation op : resource.getPayload().getOperations()) {
@@ -735,7 +748,14 @@ public class ODataBinderImpl implements ODataBinder {
         getODataValue(typeInfo == null ? null : typeInfo.getFullQualifiedName(),
             payload, resource.getContextURL(), resource.getMetadataETag()));
     odataAnnotations(payload, property);
-
+    
+    for (Operation op : resource.getPayload().getOperations()) {
+      ClientOperation operation = new ClientOperation();
+      operation.setTarget(op.getTarget());
+      operation.setTitle(op.getTitle());
+      operation.setMetadataAnchor(op.getMetadataAnchor());
+      property.getOperations().add(operation);
+    }     
     return property;
   }
 

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/eaceb01d/lib/commons-api/src/main/java/org/apache/olingo/commons/api/Constants.java
----------------------------------------------------------------------
diff --git a/lib/commons-api/src/main/java/org/apache/olingo/commons/api/Constants.java b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/Constants.java
index 88b3d86..74db088 100644
--- a/lib/commons-api/src/main/java/org/apache/olingo/commons/api/Constants.java
+++ b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/Constants.java
@@ -51,6 +51,8 @@ public interface Constants {
   String NS_ASSOCIATION_LINK_REL = "http://docs.oasis-open.org/odata/ns/relatedlinks/";
 
   String NS_MEDIA_EDIT_LINK_REL = "http://docs.oasis-open.org/odata/ns/edit-media/";
+  
+  String NS_MEDIA_READ_LINK_REL = "http://docs.oasis-open.org/odata/ns/mediaresource/";
 
   String NS_DELTA_LINK_REL = "http://docs.oasis-open.org/odata/ns/delta";
 
@@ -274,6 +276,8 @@ public interface Constants {
   QName QNAME_ATOM_ELEM_CONTENT = new QName(NS_ATOM, ATOM_ELEM_CONTENT);
 
   String ATOM_ELEM_ACTION = "action";
+  
+  String ATOM_ELEM_FUNCTION = "function";
 
   String ATOM_ELEM_INLINE = "inline";
 

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/eaceb01d/lib/commons-api/src/main/java/org/apache/olingo/commons/api/data/AbstractEntityCollection.java
----------------------------------------------------------------------
diff --git a/lib/commons-api/src/main/java/org/apache/olingo/commons/api/data/AbstractEntityCollection.java b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/data/AbstractEntityCollection.java
index 2d7a689..9521591 100644
--- a/lib/commons-api/src/main/java/org/apache/olingo/commons/api/data/AbstractEntityCollection.java
+++ b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/data/AbstractEntityCollection.java
@@ -19,6 +19,7 @@
 package org.apache.olingo.commons.api.data;
 
 import java.net.URI;
+import java.util.List;
 
 public abstract class AbstractEntityCollection extends AbstractODataObject implements Iterable<Entity> {
   public abstract Integer getCount();
@@ -26,4 +27,6 @@ public abstract class AbstractEntityCollection extends AbstractODataObject imple
   public abstract URI getNext();
 
   public abstract URI getDeltaLink();
+  
+  public abstract List<Operation> getOperations();
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/eaceb01d/lib/commons-api/src/main/java/org/apache/olingo/commons/api/data/EntityCollection.java
----------------------------------------------------------------------
diff --git a/lib/commons-api/src/main/java/org/apache/olingo/commons/api/data/EntityCollection.java b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/data/EntityCollection.java
index 86d8747..d95c536 100644
--- a/lib/commons-api/src/main/java/org/apache/olingo/commons/api/data/EntityCollection.java
+++ b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/data/EntityCollection.java
@@ -32,7 +32,8 @@ public class EntityCollection extends AbstractEntityCollection {
   private Integer count;
   private URI next;
   private URI deltaLink;
-
+  private final List<Operation> operations = new ArrayList<Operation>();
+  
   /**
    * Sets number of entries.
    *
@@ -98,6 +99,16 @@ public class EntityCollection extends AbstractEntityCollection {
   public void setDeltaLink(final URI deltaLink) {
     this.deltaLink = deltaLink;
   }
+  
+  /**
+   * Gets operations.
+   *
+   * @return operations.
+   */
+  @Override
+  public List<Operation> getOperations() {
+    return operations;
+  }  
 
   @Override
   public Iterator<Entity> iterator() {

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/eaceb01d/lib/commons-api/src/main/java/org/apache/olingo/commons/api/data/Operation.java
----------------------------------------------------------------------
diff --git a/lib/commons-api/src/main/java/org/apache/olingo/commons/api/data/Operation.java b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/data/Operation.java
index f7bf1fa..515de03 100644
--- a/lib/commons-api/src/main/java/org/apache/olingo/commons/api/data/Operation.java
+++ b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/data/Operation.java
@@ -24,13 +24,16 @@ import java.net.URI;
  * Data representation for an operation.
  */
 public class Operation {
-
+  public enum Type {ACTION, FUNCTION};
+  
   private String metadataAnchor;
 
   private String title;
 
   private URI target;
 
+  private Type type;
+  
   /**
    * Gets metadata anchor.
    *
@@ -84,5 +87,20 @@ public class Operation {
   public void setTarget(final URI target) {
     this.target = target;
   }
+  
+  /**
+   * Gets the Operation Type 
+   * @return
+   */
+  public Type getType() {
+    return type;
+  }
 
+  /**
+   * Set the Operation type
+   * @param type
+   */
+  public void setType(Type type) {
+    this.type = type;
+  }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/eaceb01d/lib/commons-api/src/main/java/org/apache/olingo/commons/api/data/Property.java
----------------------------------------------------------------------
diff --git a/lib/commons-api/src/main/java/org/apache/olingo/commons/api/data/Property.java b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/data/Property.java
index 2117241..c8ad3c8 100644
--- a/lib/commons-api/src/main/java/org/apache/olingo/commons/api/data/Property.java
+++ b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/data/Property.java
@@ -18,12 +18,16 @@
  */
 package org.apache.olingo.commons.api.data;
 
+import java.util.ArrayList;
+import java.util.List;
+
 /**
  * Data representation for a property.
  */
 public class Property extends Valuable {
 
   private String name;
+  private final List<Operation> operations = new ArrayList<Operation>();
   
   /**
    * Creates a new property
@@ -79,6 +83,15 @@ public class Property extends Valuable {
   public boolean isNull() {
     return getValue() == null || "Edm.Null".equals(getType());
   }
+  
+  /**
+   * Gets operations.
+   *
+   * @return operations.
+   */
+  public List<Operation> getOperations() {
+    return operations;
+  }  
 
   @Override
   public boolean equals(final Object o) {

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/eaceb01d/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmStream.java
----------------------------------------------------------------------
diff --git a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmStream.java b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmStream.java
index ff46b7d..b9f3a6c 100644
--- a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmStream.java
+++ b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmStream.java
@@ -21,6 +21,7 @@ package org.apache.olingo.commons.core.edm.primitivetype;
 import java.net.URI;
 import java.net.URISyntaxException;
 
+import org.apache.olingo.commons.api.data.Link;
 import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
 
 /**
@@ -69,6 +70,10 @@ public final class EdmStream extends SingletonPrimitiveType {
 
     if (returnType.isAssignableFrom(URI.class)) {
       return returnType.cast(stream);
+    } else if (returnType.isAssignableFrom(Link.class)) {
+      Link link = new Link();
+      link.setHref(value);
+      return returnType.cast(link);
     } else {
       throw new EdmPrimitiveTypeException("The value type " + returnType + " is not supported.");
     }
@@ -81,6 +86,8 @@ public final class EdmStream extends SingletonPrimitiveType {
 
     if (value instanceof URI) {
       return ((URI) value).toASCIIString();
+    } else if (value instanceof Link) {
+      return ((Link)value).getHref();
     } else {
       throw new EdmPrimitiveTypeException("The value type " + value.getClass() + " is not supported.");
     }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/eaceb01d/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ServiceRequest.java
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ServiceRequest.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ServiceRequest.java
index 67d794c..29c7134 100644
--- a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ServiceRequest.java
+++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ServiceRequest.java
@@ -220,14 +220,14 @@ public abstract class ServiceRequest {
     
     if (serilizerOptions.isAssignableFrom(EntitySerializerOptions.class)) {
       return (T) EntitySerializerOptions.with()
-          .contextURL(isODataMetadataNone(getResponseContentType()) ? null : contextUrl)
+          .contextURL(contextUrl)
           .expand(uriInfo.getExpandOption()).select(this.uriInfo.getSelectOption())
           .writeOnlyReferences(references)
           .xml10InvalidCharReplacement(xmlReplacement)
           .build();
     } else if (serilizerOptions.isAssignableFrom(EntityCollectionSerializerOptions.class)) {
       return (T) EntityCollectionSerializerOptions.with()
-          .contextURL(isODataMetadataNone(getResponseContentType()) ? null : contextUrl)
+          .contextURL(contextUrl)
           .count(uriInfo.getCountOption()).expand(uriInfo.getExpandOption())
           .select(uriInfo.getSelectOption()).writeOnlyReferences(references)
           .id(getODataRequest().getRawBaseUri() + getODataRequest().getRawODataPath())
@@ -346,9 +346,4 @@ public abstract class ServiceRequest {
     dispatcher.request.setUriInfo(uriInfo);
     return (DataRequest)dispatcher.request;
   }
-  
-  private boolean isODataMetadataNone(final ContentType contentType) {
-    return contentType.isCompatible(ContentType.JSON) 
-        && ContentType.VALUE_ODATA_METADATA_NONE.equals(contentType.getParameter(ContentType.PARAMETER_ODATA_METADATA));
-  }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/eaceb01d/lib/server-core/src/main/java/org/apache/olingo/server/core/ContentNegotiator.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/ContentNegotiator.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/ContentNegotiator.java
index 86697d5..63452f4 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/ContentNegotiator.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/ContentNegotiator.java
@@ -41,6 +41,7 @@ public final class ContentNegotiator {
           ContentType.JSON,
           ContentType.JSON_NO_METADATA,
           ContentType.APPLICATION_JSON,
+          ContentType.JSON_FULL_METADATA,
           ContentType.APPLICATION_ATOM_XML,
           ContentType.APPLICATION_XML));
 

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/eaceb01d/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataImpl.java
index 71ea0e7..b638ae7 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataImpl.java
@@ -64,7 +64,8 @@ public class ODataImpl extends OData {
       final String metadata = contentType.getParameter(ContentType.PARAMETER_ODATA_METADATA);
       if (metadata == null
           || ContentType.VALUE_ODATA_METADATA_MINIMAL.equals(metadata)
-          || ContentType.VALUE_ODATA_METADATA_NONE.equals(metadata)) {
+          || ContentType.VALUE_ODATA_METADATA_NONE.equals(metadata)
+          || ContentType.VALUE_ODATA_METADATA_FULL.equals(metadata)) {
         serializer = new ODataJsonSerializer(contentType);
       }
     } else if (contentType.isCompatible(ContentType.APPLICATION_XML)

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/eaceb01d/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/xml/ODataXmlDeserializer.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/xml/ODataXmlDeserializer.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/xml/ODataXmlDeserializer.java
index c8b5f96..21c9b37 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/xml/ODataXmlDeserializer.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/xml/ODataXmlDeserializer.java
@@ -543,7 +543,8 @@ public class ODataXmlDeserializer implements ODataDeserializer {
               }
             } else if (link.getRel().startsWith(Constants.NS_ASSOCIATION_LINK_REL)) {
               entity.getAssociationLinks().add(link);
-            } else if (link.getRel().startsWith(Constants.NS_MEDIA_EDIT_LINK_REL)) {
+            } else if (link.getRel().startsWith(Constants.NS_MEDIA_EDIT_LINK_REL) ||
+                link.getRel().startsWith(Constants.NS_MEDIA_READ_LINK_REL)) {
               final Attribute metag = event.asStartElement().getAttributeByName(etagQName);
               if (metag != null) {
                 link.setMediaETag(metag.getValue());

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/eaceb01d/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializer.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializer.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializer.java
index 396261f..759ae5c 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializer.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializer.java
@@ -18,6 +18,9 @@
  */
 package org.apache.olingo.server.core.serializer.json;
 
+import static org.apache.olingo.server.core.serializer.utils.ContentTypeHelper.isODataMetadataFull;
+import static org.apache.olingo.server.core.serializer.utils.ContentTypeHelper.isODataMetadataNone;
+
 import java.io.IOException;
 import java.io.OutputStream;
 import java.util.Collections;
@@ -33,6 +36,7 @@ import org.apache.olingo.commons.api.data.Entity;
 import org.apache.olingo.commons.api.data.EntityIterator;
 import org.apache.olingo.commons.api.data.Link;
 import org.apache.olingo.commons.api.data.Linked;
+import org.apache.olingo.commons.api.data.Operation;
 import org.apache.olingo.commons.api.data.Property;
 import org.apache.olingo.commons.api.edm.EdmComplexType;
 import org.apache.olingo.commons.api.edm.EdmEntitySet;
@@ -68,7 +72,6 @@ import org.apache.olingo.server.core.ODataWritableContent;
 import org.apache.olingo.server.core.serializer.AbstractODataSerializer;
 import org.apache.olingo.server.core.serializer.SerializerResultImpl;
 import org.apache.olingo.server.core.serializer.utils.CircleStreamBuffer;
-import org.apache.olingo.server.core.serializer.utils.ContentTypeHelper;
 import org.apache.olingo.server.core.serializer.utils.ContextURLBuilder;
 import org.apache.olingo.server.core.serializer.utils.ExpandSelectHelper;
 import org.apache.olingo.server.core.uri.UriHelperImpl;
@@ -79,11 +82,11 @@ import com.fasterxml.jackson.core.JsonGenerator;
 public class ODataJsonSerializer extends AbstractODataSerializer {
 
   private final boolean isIEEE754Compatible;
-  private final boolean isODataMetadataNone;
+  private final ContentType contentType;
 
   public ODataJsonSerializer(final ContentType contentType) {
+    this.contentType = contentType;
     isIEEE754Compatible = isODataIEEE754Compatible(contentType);
-    isODataMetadataNone = ContentTypeHelper.isODataMetadataNone(contentType);
   }
 
   @Override
@@ -96,7 +99,8 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
       CircleStreamBuffer buffer = new CircleStreamBuffer();
       outputStream = buffer.getOutputStream();
       JsonGenerator json = new JsonFactory().createGenerator(outputStream);
-      new ServiceDocumentJsonSerializer(metadata, serviceRoot, isODataMetadataNone).writeServiceDocument(json);
+      new ServiceDocumentJsonSerializer(metadata, serviceRoot, 
+          isODataMetadataNone(contentType)).writeServiceDocument(json);
 
       json.close();
       outputStream.close();
@@ -158,6 +162,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
       if (options != null && options.getCount() != null && options.getCount().getValue()) {
         writeCount(entitySet, json);
       }
+      writeOperations(entitySet.getOperations(), json);
       json.writeFieldName(Constants.VALUE);
       if (options == null) {
         writeEntitySet(metadata, entityType, entitySet, null, null, false, json);
@@ -251,7 +256,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
   }
 
   ContextURL checkContextURL(final ContextURL contextURL) throws SerializerException {
-    if (isODataMetadataNone) {
+    if (isODataMetadataNone(contentType)) {
       return null;
     } else if (contextURL == null) {
       throw new SerializerException("ContextURL null!", SerializerException.MessageKeys.NO_CONTEXT_URL);
@@ -308,7 +313,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
       final JsonGenerator json)
       throws IOException, SerializerException {
     json.writeStartObject();
-    if (!isODataMetadataNone) {
+    if (!isODataMetadataNone(contentType)) {
       // top-level entity
       if (contextURL != null) {
         writeContextURL(contextURL, json);
@@ -336,18 +341,43 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
       json.writeStringField(Constants.JSON_ID, getEntityId(entity));
     } else {
       final EdmEntityType resolvedType = resolveEntityType(metadata, entityType, entity.getType());
-      if (!isODataMetadataNone && !resolvedType.equals(entityType)) {
+      if ((!isODataMetadataNone(contentType) && !resolvedType.equals(entityType)) 
+          || isODataMetadataFull(contentType)) {
         json.writeStringField(Constants.JSON_TYPE, "#" + entity.getType());
       }
-      if (!isODataMetadataNone && !areKeyPredicateNamesSelected(select, resolvedType)) {
+      if ((!isODataMetadataNone(contentType) && !areKeyPredicateNamesSelected(select, resolvedType)) 
+          || isODataMetadataFull(contentType)) {
         json.writeStringField(Constants.JSON_ID, getEntityId(entity));
       }
+      
+      if (isODataMetadataFull(contentType)) {
+        if (entity.getSelfLink() != null) {
+          json.writeStringField(Constants.JSON_READ_LINK, entity.getSelfLink().getHref());
+        }
+        if (entity.getEditLink() != null) {
+          json.writeStringField(Constants.JSON_EDIT_LINK, entity.getEditLink().getHref());
+        }
+      }
+      
       writeProperties(metadata, resolvedType, entity.getProperties(), select, json);
       writeNavigationProperties(metadata, resolvedType, entity, expand, json);
+      writeOperations(entity.getOperations(), json);
       json.writeEndObject();
     }
   }
 
+  private void writeOperations(final List<Operation> operations, final JsonGenerator json)
+      throws IOException {
+    if (isODataMetadataFull(contentType)) {
+      for (Operation operation : operations) {
+        json.writeObjectFieldStart(operation.getMetadataAnchor());
+        json.writeStringField(Constants.ATTR_TITLE, operation.getTitle());
+        json.writeStringField(Constants.ATTR_TARGET, operation.getTarget().toASCIIString());
+        json.writeEndObject();
+      }
+    }
+  }
+
   protected EdmEntityType resolveEntityType(final ServiceMetadata metadata, final EdmEntityType baseType,
       final String derivedTypeName) throws SerializerException {
     if (derivedTypeName == null ||
@@ -440,6 +470,17 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
               json);
         }
       }
+    } else if (isODataMetadataFull(contentType)) {
+      for (final String propertyName : type.getNavigationPropertyNames()) {
+        final Link navigationLink = linked.getNavigationLink(propertyName);
+        if (navigationLink != null) {
+          json.writeStringField(propertyName + Constants.JSON_NAVIGATION_LINK, navigationLink.getHref());  
+        }
+        final Link associationLink = linked.getAssociationLink(propertyName);
+        if (associationLink != null) {
+          json.writeStringField(propertyName + Constants.JSON_ASSOCIATION_LINK, associationLink.getHref());  
+        }
+      }
     }
   }
 
@@ -484,28 +525,79 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
       }
     }
   }
+  
+  private boolean isStreamProperty(EdmProperty edmProperty) {
+    final EdmType type = edmProperty.getType();
+    return (edmProperty.isPrimitive() && type == EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Stream));    
+  }
 
-  protected void writeProperty(final ServiceMetadata metadata, final EdmProperty edmProperty, final Property property,
+  protected void writeProperty(final ServiceMetadata metadata,
+      final EdmProperty edmProperty, final Property property,
       final Set<List<String>> selectedPaths, final JsonGenerator json)
       throws IOException, SerializerException {
-    json.writeFieldName(edmProperty.getName());
-    if (property == null || property.isNull()) {
+    boolean isStreamProperty = isStreamProperty(edmProperty);
+    writePropertyType(edmProperty, property, json);
+    if (!isStreamProperty) {
+      json.writeFieldName(edmProperty.getName());
+    }
+    if ((property == null || property.isNull())) {
       if (edmProperty.isNullable() == Boolean.FALSE) {
         throw new SerializerException("Non-nullable property not present!",
             SerializerException.MessageKeys.MISSING_PROPERTY, edmProperty.getName());
       } else {
-        if (edmProperty.isCollection()) {
-          json.writeStartArray();
-          json.writeEndArray();
-        } else {
-          json.writeNull();
+        if (!isStreamProperty) {
+          if (edmProperty.isCollection()) {
+            json.writeStartArray();
+            json.writeEndArray();
+          } else {
+            json.writeNull();
+          }
         }
       }
     } else {
       writePropertyValue(metadata, edmProperty, property, selectedPaths, json);
     }
   }
-
+  
+  private void writePropertyType(final EdmProperty edmProperty, final Property property,
+      final JsonGenerator json) throws SerializerException, IOException {
+    if(!isODataMetadataFull(contentType)) {
+      return;
+    }
+    String typeName = edmProperty.getName()+Constants.JSON_TYPE;
+    final EdmType type = edmProperty.getType();
+    if (type.getKind() == EdmTypeKind.ENUM || type.getKind() == EdmTypeKind.DEFINITION) {
+      if (edmProperty.isCollection()) {
+        json.writeStringField(typeName, 
+            "#Collection("+type.getFullQualifiedName().getFullQualifiedNameAsString()+")");
+      } else {
+        json.writeStringField(typeName, "#"+type.getFullQualifiedName().getFullQualifiedNameAsString());
+      }      
+    } else if (edmProperty.isPrimitive()) {
+      if (edmProperty.isCollection()) {
+        json.writeStringField(typeName, 
+            "#Collection("+type.getFullQualifiedName().getName()+")");        
+      } else {
+        // exclude the properties that can be heuristically determined
+        if (type != EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Boolean) &&
+            type != EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Double) &&
+            type != EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.String)) {
+          json.writeStringField(typeName, 
+              "#"+type.getFullQualifiedName().getName());                  
+        }
+      }
+    } else if (type.getKind() == EdmTypeKind.COMPLEX) {
+      // non-collection case written in writeComplex method directly.
+      if (edmProperty.isCollection()) {
+        json.writeStringField(typeName, 
+            "#Collection("+type.getFullQualifiedName().getFullQualifiedNameAsString()+")");        
+      }
+    } else {
+      throw new SerializerException("Property type not yet supported!",
+          SerializerException.MessageKeys.UNSUPPORTED_PROPERTY_TYPE, edmProperty.getName());
+    }    
+  }
+  
   private void writePropertyValue(final ServiceMetadata metadata, final EdmProperty edmProperty,
       final Property property, final Set<List<String>> selectedPaths, final JsonGenerator json)
       throws IOException, SerializerException {
@@ -550,7 +642,8 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
       case COLLECTION_PRIMITIVE:
       case COLLECTION_ENUM:
         try {
-          writePrimitiveValue(type, value, isNullable, maxLength, precision, scale, isUnicode, json);
+          writePrimitiveValue(property.getName(), type, value, isNullable,
+              maxLength, precision, scale, isUnicode, json);
         } catch (EdmPrimitiveTypeException e) {
           throw new SerializerException("Wrong value for property!", e,
               SerializerException.MessageKeys.WRONG_PROPERTY_VALUE,
@@ -591,13 +684,13 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
       final Boolean isUnicode, final JsonGenerator json)
       throws EdmPrimitiveTypeException, IOException, SerializerException {
     if (property.isPrimitive()) {
-      writePrimitiveValue(type, property.asPrimitive(),
+      writePrimitiveValue(property.getName(), type, property.asPrimitive(),
           isNullable, maxLength, precision, scale, isUnicode, json);
     } else if (property.isGeospatial()) {
       throw new SerializerException("Property type not yet supported!",
           SerializerException.MessageKeys.UNSUPPORTED_PROPERTY_TYPE, property.getName());
     } else if (property.isEnum()) {
-      writePrimitiveValue(type, property.asEnum(),
+      writePrimitiveValue(property.getName(), type, property.asEnum(),
           isNullable, maxLength, precision, scale, isUnicode, json);
     } else {
       throw new SerializerException("Inconsistent property type!",
@@ -605,7 +698,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
     }
   }
 
-  protected void writePrimitiveValue(final EdmPrimitiveType type, final Object primitiveValue,
+  protected void writePrimitiveValue(final String name, final EdmPrimitiveType type, final Object primitiveValue,
       final Boolean isNullable, final Integer maxLength, final Integer precision, final Integer scale,
       final Boolean isUnicode, final JsonGenerator json) throws EdmPrimitiveTypeException, IOException {
     final String value = type.valueToString(primitiveValue,
@@ -624,6 +717,26 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
         || type == EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Int64))
         && !isIEEE754Compatible) {
       json.writeNumber(value);
+    } else if (type == EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Stream)) {
+      if (primitiveValue instanceof Link) {
+        Link stream = (Link)primitiveValue;
+        if (!isODataMetadataNone(contentType)) {
+          if (stream.getMediaETag() != null) {
+            json.writeStringField(name+Constants.JSON_MEDIA_ETAG, stream.getMediaETag());
+          }
+          if (stream.getType() != null) {
+            json.writeStringField(name+Constants.JSON_MEDIA_CONTENT_TYPE, stream.getType());
+          }
+        }
+        if (isODataMetadataFull(contentType)) {
+          if (stream.getRel() != null && stream.getRel().equals(Constants.NS_MEDIA_READ_LINK_REL)) {
+            json.writeStringField(name+Constants.JSON_MEDIA_READ_LINK, stream.getHref());
+          }
+          if (stream.getRel() == null || stream.getRel().equals(Constants.NS_MEDIA_EDIT_LINK_REL)) {
+            json.writeStringField(name+Constants.JSON_MEDIA_EDIT_LINK, stream.getHref());
+          }
+        }
+      }
     } else {
       json.writeString(value);
     }
@@ -637,9 +750,8 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
 
     final EdmComplexType resolvedType = resolveComplexType(metadata,
         type, complexProperty.getType());
-    if (!isODataMetadataNone && !resolvedType.equals(type)) {
-      json.writeStringField(Constants.JSON_TYPE,
-          "#" + complexProperty.getType());
+    if (!isODataMetadataNone(contentType) && !resolvedType.equals(type) || isODataMetadataFull(contentType)) {
+      json.writeStringField(Constants.JSON_TYPE, "#" + complexProperty.getType());
     }
 
     for (final String propertyName : resolvedType.getPropertyNames()) {
@@ -675,6 +787,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
       json.writeStartObject();
       writeContextURL(contextURL, json);
       writeMetadataETag(metadata, json);
+      writeOperations(property.getOperations(), json);
       if (property.isNull()) {
         throw new SerializerException("Property value can not be null.", SerializerException.MessageKeys.NULL_INPUT);
       } else {
@@ -717,11 +830,12 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
       JsonGenerator json = new JsonFactory().createGenerator(outputStream);
       json.writeStartObject();
       writeContextURL(contextURL, json);
-      writeMetadataETag(metadata, json);
+      writeMetadataETag(metadata, json);      
       final EdmComplexType resolvedType = resolveComplexType(metadata, type, property.getType());
-      if (!isODataMetadataNone && !resolvedType.equals(type)) {
+      if (!isODataMetadataNone(contentType) && !resolvedType.equals(type) || isODataMetadataFull(contentType)) {
         json.writeStringField(Constants.JSON_TYPE, "#" + property.getType());
       }
+      writeOperations(property.getOperations(), json);      
       final List<Property> values =
           property.isNull() ? Collections.<Property> emptyList() : property.asComplex().getValue();
       writeProperties(metadata, type, values, options == null ? null : options.getSelect(), json);
@@ -756,6 +870,10 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
       json.writeStartObject();
       writeContextURL(contextURL, json);
       writeMetadataETag(metadata, json);
+      if (isODataMetadataFull(contentType)) {
+        json.writeStringField(Constants.JSON_TYPE,  "#Collection("+type.getFullQualifiedName().getName()+")");
+      }
+      writeOperations(property.getOperations(), json);
       json.writeFieldName(Constants.VALUE);
       writePrimitiveCollection(type, property,
           options == null ? null : options.isNullable(),
@@ -790,6 +908,11 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
       json.writeStartObject();
       writeContextURL(contextURL, json);
       writeMetadataETag(metadata, json);
+      if (isODataMetadataFull(contentType)) {
+        json.writeStringField(Constants.JSON_TYPE, 
+            "#Collection("+type.getFullQualifiedName().getFullQualifiedNameAsString()+")");                
+      }
+      writeOperations(property.getOperations(), json);
       json.writeFieldName(Constants.VALUE);
       writeComplexCollection(metadata, type, property, null, json);
       json.writeEndObject();
@@ -882,13 +1005,13 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
   }
 
   void writeContextURL(final ContextURL contextURL, final JsonGenerator json) throws IOException {
-    if (!isODataMetadataNone && contextURL != null) {
+    if (!isODataMetadataNone(contentType) && contextURL != null) {
       json.writeStringField(Constants.JSON_CONTEXT, ContextURLBuilder.create(contextURL).toASCIIString());
     }
   }
 
   void writeMetadataETag(final ServiceMetadata metadata, final JsonGenerator json) throws IOException {
-    if (!isODataMetadataNone
+    if (!isODataMetadataNone(contentType)
         && metadata != null
         && metadata.getServiceMetadataETagSupport() != null
         && metadata.getServiceMetadataETagSupport().getMetadataETag() != null) {

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/eaceb01d/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/utils/ContentTypeHelper.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/utils/ContentTypeHelper.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/utils/ContentTypeHelper.java
index 68d85f7..99c0343 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/utils/ContentTypeHelper.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/utils/ContentTypeHelper.java
@@ -30,4 +30,9 @@ public class ContentTypeHelper {
     return contentType.isCompatible(ContentType.APPLICATION_JSON)
         && ContentType.VALUE_ODATA_METADATA_NONE.equals(contentType.getParameter(ContentType.PARAMETER_ODATA_METADATA));
   }
+  
+  public static boolean isODataMetadataFull(final ContentType contentType) {
+    return contentType.isCompatible(ContentType.APPLICATION_JSON)
+        && ContentType.VALUE_ODATA_METADATA_FULL.equals(contentType.getParameter(ContentType.PARAMETER_ODATA_METADATA));
+  }  
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/eaceb01d/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/xml/ODataXmlSerializer.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/xml/ODataXmlSerializer.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/xml/ODataXmlSerializer.java
index fecf920..b3d815b 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/xml/ODataXmlSerializer.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/xml/ODataXmlSerializer.java
@@ -39,6 +39,7 @@ import org.apache.olingo.commons.api.data.AbstractEntityCollection;
 import org.apache.olingo.commons.api.data.EntityIterator;
 import org.apache.olingo.commons.api.data.Link;
 import org.apache.olingo.commons.api.data.Linked;
+import org.apache.olingo.commons.api.data.Operation;
 import org.apache.olingo.commons.api.data.Property;
 import org.apache.olingo.commons.api.edm.EdmComplexType;
 import org.apache.olingo.commons.api.edm.EdmEntitySet;
@@ -240,7 +241,7 @@ public class ODataXmlSerializer extends AbstractODataSerializer {
       writer.writeAttribute(METADATA, NS_METADATA, Constants.CONTEXT,
           ContextURLBuilder.create(contextURL).toASCIIString());
       writeMetadataETag(metadata, writer);
-
+      writeOperations(entitySet.getOperations(), writer);
       if (options != null && options.getId() != null) {
         writer.writeStartElement(ATOM, Constants.ATOM_ELEM_ID, NS_ATOM);
         writer.writeCharacters(options.getId());
@@ -487,9 +488,24 @@ public class ODataXmlSerializer extends AbstractODataSerializer {
     if (!entityType.hasStream()) { // content
       writer.writeEndElement();
     }
+    
+    writeOperations(entity.getOperations(), writer);
+    
     writer.writeEndElement(); // entry
   }
 
+  private void writeOperations(final List<Operation> operations,
+      final XMLStreamWriter writer) throws XMLStreamException {
+    for (Operation operation : operations) {
+      boolean action = (operation.getType() != null && operation.getType() == Operation.Type.ACTION);
+      writer.writeStartElement(METADATA, action?Constants.ATOM_ELEM_ACTION:Constants.ATOM_ELEM_FUNCTION, NS_METADATA);
+      writer.writeAttribute(Constants.ATTR_METADATA, operation.getMetadataAnchor());
+      writer.writeAttribute(Constants.ATTR_TITLE, operation.getTitle());
+      writer.writeAttribute(Constants.ATTR_TARGET, operation.getTarget().toASCIIString());
+      writer.writeEndElement();
+    }
+  }
+
   private void writerAuthorInfo(final String title, final XMLStreamWriter writer) throws XMLStreamException {
     writer.writeStartElement(NS_ATOM, Constants.ATTR_TITLE);
     if (title != null) {

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/eaceb01d/lib/server-core/src/test/java/org/apache/olingo/server/core/ContentNegotiatorTest.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/test/java/org/apache/olingo/server/core/ContentNegotiatorTest.java b/lib/server-core/src/test/java/org/apache/olingo/server/core/ContentNegotiatorTest.java
index ce0abe7..ae6373c 100644
--- a/lib/server-core/src/test/java/org/apache/olingo/server/core/ContentNegotiatorTest.java
+++ b/lib/server-core/src/test/java/org/apache/olingo/server/core/ContentNegotiatorTest.java
@@ -99,7 +99,6 @@ public class ContentNegotiatorTest {
       { null,                   "a/a",            null,                  "b/b"            },
       { null,                   "a/a;x=y",        null,                  "a/a;v=w"        },
       { null,                   null,             "a/a;x=y",             "a/a;v=w"        },
-      { null,                   null,             ACCEPT_CASE_FULL,      null             }, // not yet supported
       { null,                   null,             "*",                   null             },
       { null,                   "a/b;charset=ISO-8859-1", null,          "a/b"            },
       { null,                   null,             "a/b;charset=ISO-8859-1", "a/b"         },

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/eaceb01d/lib/server-core/src/test/java/org/apache/olingo/server/core/ODataImplTest.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/test/java/org/apache/olingo/server/core/ODataImplTest.java b/lib/server-core/src/test/java/org/apache/olingo/server/core/ODataImplTest.java
index c289b93..e0875e7 100644
--- a/lib/server-core/src/test/java/org/apache/olingo/server/core/ODataImplTest.java
+++ b/lib/server-core/src/test/java/org/apache/olingo/server/core/ODataImplTest.java
@@ -35,11 +35,8 @@ public class ODataImplTest {
     assertNotNull(odata.createSerializer(ContentType.JSON_NO_METADATA));
     assertNotNull(odata.createSerializer(ContentType.JSON));
     assertNotNull(odata.createSerializer(ContentType.APPLICATION_JSON));
-  }
-
-  @Test(expected = SerializerException.class)
-  public void jsonSerializerForODataMetadataFull() throws SerializerException {
-    odata.createSerializer(ContentType.JSON_FULL_METADATA);
+    assertNotNull(odata.createSerializer(ContentType.JSON_FULL_METADATA));
+    
   }
 
   @Test


[2/3] olingo-odata4 git commit: OLINGO-567: Support for odata.metadata=full

Posted by ra...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/eaceb01d/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/ActionData.java
----------------------------------------------------------------------
diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/ActionData.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/ActionData.java
index 4fae878..51f51c8 100644
--- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/ActionData.java
+++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/ActionData.java
@@ -40,6 +40,7 @@ import org.apache.olingo.commons.api.http.HttpStatusCode;
 import org.apache.olingo.server.api.OData;
 import org.apache.olingo.server.api.serializer.SerializerException;
 import org.apache.olingo.server.tecsvc.data.DataProvider.DataProviderException;
+import org.apache.olingo.server.tecsvc.provider.ComplexTypeProvider;
 
 public class ActionData {
 
@@ -118,6 +119,7 @@ public class ActionData {
 
   private static Property createCTTwoPrimComplexProperty(final String name, final Short number, final String text) {
     return DataCreator.createComplex(name,
+        ComplexTypeProvider.nameCTTwoPrim.getFullQualifiedNameAsString(),
         DataCreator.createPrimitive("PropertyInt16", number),
         DataCreator.createPrimitive("PropertyString", text));
   }
@@ -244,18 +246,23 @@ public class ActionData {
     Entity entity = new Entity()
         .addProperty(DataCreator.createPrimitive("PropertyInt16", number))
         .addProperty(DataCreator.createPrimitive("PropertyString", "UARTCollETKeyNavParam int16 value: " + number))
-        .addProperty(DataCreator.createComplex("PropertyCompNav", 
+        .addProperty(DataCreator.createComplex("PropertyCompNav",
+            ComplexTypeProvider.nameCTNavFiveProp.getFullQualifiedNameAsString(),
             DataCreator.createPrimitive("PropertyInt16", (short) 0)))
         .addProperty(createKeyNavAllPrimComplexValue("PropertyCompAllPrim"))
         .addProperty(DataCreator.createComplex("PropertyCompTwoPrim", 
+              ComplexTypeProvider.nameCTTwoPrim.getFullQualifiedNameAsString(),
               DataCreator.createPrimitive("PropertyInt16", (short) 0),
               DataCreator.createPrimitive("PropertyString", ""))).addProperty(
               DataCreator.createPrimitiveCollection("CollPropertyString"))
         .addProperty(DataCreator.createPrimitiveCollection("CollPropertyInt16"))
-        .addProperty(DataCreator.createComplexCollection("CollPropertyComp"))
-        .addProperty(DataCreator.createComplex("PropertyCompCompNav", 
+        .addProperty(DataCreator.createComplexCollection("CollPropertyComp",
+            ComplexTypeProvider.nameCTPrimComp.getFullQualifiedNameAsString()))
+        .addProperty(DataCreator.createComplex("PropertyCompCompNav",
+            ComplexTypeProvider.nameCTCompNav.getFullQualifiedNameAsString(),
             DataCreator.createPrimitive("PropertyString", ""),
             DataCreator.createComplex("PropertyCompNav", 
+                ComplexTypeProvider.nameCTNavFiveProp.getFullQualifiedNameAsString(),
                 DataCreator.createPrimitive("PropertyInt16", (short) 0))));
     setEntityId(entity, "ESKeyNav", oData, edm);
     return entity;
@@ -273,6 +280,7 @@ public class ActionData {
 
   protected static Property createKeyNavAllPrimComplexValue(final String name) {
     return DataCreator.createComplex(name,
+        ComplexTypeProvider.nameCTAllPrim.getFullQualifiedNameAsString(),
         DataCreator.createPrimitive("PropertyString", ""),
         DataCreator.createPrimitive("PropertyBinary", new byte[] {}),
         DataCreator.createPrimitive("PropertyBoolean", false),

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/eaceb01d/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataCreator.java
----------------------------------------------------------------------
diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataCreator.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataCreator.java
index 1241bc5..aac9a34 100644
--- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataCreator.java
+++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataCreator.java
@@ -36,16 +36,25 @@ import org.apache.olingo.commons.api.data.ComplexValue;
 import org.apache.olingo.commons.api.data.Entity;
 import org.apache.olingo.commons.api.data.EntityCollection;
 import org.apache.olingo.commons.api.data.Link;
+import org.apache.olingo.commons.api.data.Operation;
 import org.apache.olingo.commons.api.data.Property;
 import org.apache.olingo.commons.api.data.ValueType;
 import org.apache.olingo.commons.api.edm.Edm;
 import org.apache.olingo.commons.api.edm.EdmEntitySet;
 import org.apache.olingo.commons.api.edm.EdmEntityType;
+import org.apache.olingo.commons.api.edm.FullQualifiedName;
+import org.apache.olingo.commons.api.edm.provider.CsdlAction;
+import org.apache.olingo.commons.api.edm.provider.CsdlFunction;
+import org.apache.olingo.commons.api.edm.provider.CsdlParameter;
+import org.apache.olingo.commons.api.ex.ODataException;
 import org.apache.olingo.server.api.OData;
 import org.apache.olingo.server.api.serializer.SerializerException;
 import org.apache.olingo.server.api.uri.UriHelper;
+import org.apache.olingo.server.tecsvc.provider.ActionProvider;
 import org.apache.olingo.server.tecsvc.provider.ComplexTypeProvider;
 import org.apache.olingo.server.tecsvc.provider.EntityTypeProvider;
+import org.apache.olingo.server.tecsvc.provider.FunctionProvider;
+import org.apache.olingo.server.tecsvc.provider.SchemaProvider;
 
 public class DataCreator {
 
@@ -77,6 +86,7 @@ public class DataCreator {
     data.put("ESCompMixPrimCollComp", createESCompMixPrimCollComp(edm, odata));
     data.put("ESMixEnumDefCollComp", createESMixEnumDefCollComp(edm, odata));
     data.put("ESStream", createESStream(edm, odata));
+    data.put("ESWithStream", createESWithStream(edm, odata));
 
     linkESTwoPrim(data);
     linkESAllPrim(data);
@@ -93,7 +103,7 @@ public class DataCreator {
 
     setEntityType(entityCollection, edm.getEntityType(EntityTypeProvider.nameETMixEnumDefCollComp));
     createEntityId(edm, odata, "ESMixEnumDefCollComp", entityCollection);
-
+    createOperations("ESMixEnumDefCollComp", entityCollection, EntityTypeProvider.nameETMixEnumDefCollComp);
     return entityCollection;
   }
 
@@ -114,7 +124,7 @@ public class DataCreator {
 
     setEntityType(entityCollection, edm.getEntityType(EntityTypeProvider.nameETCompMixPrimCollComp));
     createEntityId(edm, odata, "ESCompMixPrimCollComp", entityCollection);
-
+    createOperations("ESCompMixPrimCollComp", entityCollection, EntityTypeProvider.nameETCompMixPrimCollComp);
     return entityCollection;
   }
 
@@ -123,6 +133,7 @@ public class DataCreator {
     return new Entity()
         .addProperty(createPrimitive("PropertyInt16", propertyInt16))
         .addProperty(createComplex("PropertyMixedPrimCollComp",
+            ComplexTypeProvider.nameCTMixPrimCollComp.getFullQualifiedNameAsString(),
             createPrimitive("PropertyInt16", (short) 1),
             createPrimitiveCollection("CollPropertyString",
                 "Employee1@company.example",
@@ -130,10 +141,12 @@ public class DataCreator {
                 "Employee3@company.example"
             ),
             createComplex("PropertyComp",
+                ComplexTypeProvider.nameCTTwoPrim.getFullQualifiedNameAsString(),
                 createPrimitive("PropertyInt16", (short) 333),
                 createPrimitive("PropertyString", "TEST123")
             ),
             createComplexCollection("CollPropertyComp",
+                ComplexTypeProvider.nameCTTwoPrim.getFullQualifiedNameAsString(),
                 Arrays.asList(new Property[] {
                     createPrimitive("PropertyInt16", (short) 222),
                     createPrimitive("PropertyString", "TEST9876")
@@ -166,7 +179,7 @@ public class DataCreator {
 
     setEntityType(entityCollection, edm.getEntityType(EntityTypeProvider.nameETBase));
     createEntityId(edm, odata, "ESBase", entityCollection);
-
+    createOperations("ESBase", entityCollection, EntityTypeProvider.nameETBase);
     return entityCollection;
   }
 
@@ -176,11 +189,14 @@ public class DataCreator {
     entityCollection.getEntities().add(new Entity()
         .addProperty(createPrimitive("PropertyInt16", (short) 1))
         .addProperty(createComplex("PropertyComp",
+            ComplexTypeProvider.nameCTTwoPrim.getFullQualifiedNameAsString(),
             createPrimitive("PropertyInt16", (short) 11),
             createPrimitive("PropertyString", "Num11")
             ))
         .addProperty(createComplex("PropertyCompComp",
+            ComplexTypeProvider.nameCTCompComp.getFullQualifiedNameAsString(),
             createComplex("PropertyComp",
+                ComplexTypeProvider.nameCTTwoPrim.getFullQualifiedNameAsString(),
                 createPrimitive("PropertyInt16", (short) 111),
                 createPrimitive("PropertyString", "Num111")
             )
@@ -189,7 +205,7 @@ public class DataCreator {
 
     setEntityType(entityCollection, edm.getEntityType(EntityTypeProvider.nameETFourKeyAlias));
     createEntityId(edm, odata, "ESFourKeyAlias", entityCollection);
-
+    createOperations("ESFourKeyAlias", entityCollection, EntityTypeProvider.nameETFourKeyAlias);
     return entityCollection;
   }
 
@@ -201,6 +217,7 @@ public class DataCreator {
 
     setEntityType(entityCollection, edm.getEntityType(EntityTypeProvider.nameETCompCollAllPrim));
     createEntityId(edm, odata, "ESCompCollAllPrim", entityCollection);
+    createOperations("ESCompCollAllPrim", entityCollection, EntityTypeProvider.nameETCompCollAllPrim);
     return entityCollection;
   }
 
@@ -208,6 +225,7 @@ public class DataCreator {
     return new Entity()
         .addProperty(createPrimitive("PropertyInt16", propertyInt16))
         .addProperty(createComplex("PropertyComp",
+            ComplexTypeProvider.nameCTCollAllPrim.getFullQualifiedNameAsString(),
             createPrimitiveCollection("CollPropertyString",
                 "Employee1@company.example",
                 "Employee2@company.example",
@@ -305,7 +323,7 @@ public class DataCreator {
 
     setEntityType(entityCollection, edm.getEntityType(EntityTypeProvider.nameETBaseTwoKeyNav));
     createEntityId(edm, odata, "ESBaseTwoKeyNav", entityCollection);
-
+    createOperations("ESBaseTwoKeyNav", entityCollection, EntityTypeProvider.nameETBaseTwoKeyNav);
     return entityCollection;
   }
 
@@ -331,7 +349,7 @@ public class DataCreator {
 
     setEntityType(entityCollection, edm.getEntityType(EntityTypeProvider.nameETTwoBase));
     createEntityId(edm, odata, "ESTwoBase", entityCollection);
-
+    createOperations("ESTwoBase", entityCollection, EntityTypeProvider.nameETTwoBase);
     return entityCollection;
   }
 
@@ -423,6 +441,7 @@ public class DataCreator {
 
     setEntityType(entityCollection, edm.getEntityType(EntityTypeProvider.nameETAllNullable));
     createEntityId(edm, odata, "ESAllNullable", entityCollection);
+    createOperations("ESAllNullable", entityCollection, EntityTypeProvider.nameETAllNullable);
     return entityCollection;
   }
 
@@ -438,7 +457,7 @@ public class DataCreator {
 
     setEntityType(entityCollection, edm.getEntityType(EntityTypeProvider.nameETTwoKeyTwoPrim));
     createEntityId(edm, odata, "ESTwoKeyTwoPrim", entityCollection);
-
+    createOperations("ESTwoKeyTwoPrim", entityCollection, EntityTypeProvider.nameETTwoKeyTwoPrim);
     return entityCollection;
   }
 
@@ -459,7 +478,7 @@ public class DataCreator {
 
     setEntityType(entityCollection, edm.getEntityType(EntityTypeProvider.nameETServerSidePaging));
     createEntityId(edm, odata, "ESServerSidePaging", entityCollection);
-
+    createOperations("ESServerSidePaging", entityCollection, EntityTypeProvider.nameETServerSidePaging);
     return entityCollection;
   }
 
@@ -472,7 +491,7 @@ public class DataCreator {
 
     setEntityType(entityCollection, edm.getEntityType(EntityTypeProvider.nameETKeyNav));
     createEntityId(edm, odata, "ESKeyNav", entityCollection);
-
+    createOperations("ESKeyNav", entityCollection, EntityTypeProvider.nameETKeyNav);
     return entityCollection;
   }
 
@@ -482,9 +501,11 @@ public class DataCreator {
         .addProperty(createPrimitive("PropertyInt16", propertyInt16))
         .addProperty(createPrimitive("PropertyString", propertyString))
         .addProperty(createComplex("PropertyCompNav",
+            ComplexTypeProvider.nameCTNavFiveProp.getFullQualifiedNameAsString(),
             createPrimitive("PropertyInt16", 1)))
         .addProperty(createKeyNavAllPrimComplexValue("PropertyCompAllPrim"))
         .addProperty(createComplex("PropertyCompTwoPrim",
+            ComplexTypeProvider.nameCTTwoPrim.getFullQualifiedNameAsString(),
             createPrimitive("PropertyInt16", (short) 16),
             createPrimitive("PropertyString", "Test123")))
         .addProperty(createPrimitiveCollection("CollPropertyString",
@@ -496,6 +517,7 @@ public class DataCreator {
             (short) 2000,
             (short) 30112))
         .addProperty(createComplexCollection("CollPropertyComp",
+            ComplexTypeProvider.nameCTPrimComp.getFullQualifiedNameAsString(),
             Arrays.asList(
                 createPrimitive("PropertyInt16", (short) 1),
                 createKeyNavAllPrimComplexValue("PropertyComp")),
@@ -506,8 +528,10 @@ public class DataCreator {
                 createPrimitive("PropertyInt16", (short) 3),
                 createKeyNavAllPrimComplexValue("PropertyComp"))))
         .addProperty(createComplex("PropertyCompCompNav",
+            ComplexTypeProvider.nameCTCompNav.getFullQualifiedNameAsString(),
             createPrimitive("PropertyString", "1"),
             createComplex("PropertyCompNav",
+                ComplexTypeProvider.nameCTNavFiveProp.getFullQualifiedNameAsString(),
                 createPrimitive("PropertyInt16", (short) 1))));
   }
 
@@ -521,7 +545,7 @@ public class DataCreator {
 
     setEntityType(entityCollection, edm.getEntityType(EntityTypeProvider.nameETTwoKeyNav));
     createEntityId(edm, odata, "ESTwoKeyNav", entityCollection);
-
+    createOperations("ESTwoKeyNav", entityCollection, EntityTypeProvider.nameETTwoKeyNav);
     return entityCollection;
   }
 
@@ -531,8 +555,10 @@ public class DataCreator {
         .addProperty(createPrimitive("PropertyInt16", propertyInt16))
         .addProperty(createPrimitive("PropertyString", propertyString))
         .addProperty(createComplex("PropertyComp",
+            ComplexTypeProvider.nameCTPrimComp.getFullQualifiedNameAsString(),
             createPrimitive("PropertyInt16", 11),
             createComplex("PropertyComp",
+                ComplexTypeProvider.nameCTAllPrim.getFullQualifiedNameAsString(),
                 createPrimitive("PropertyString", "StringValue"),
                 createPrimitive("PropertyBinary", new byte[] { 1, 35, 69, 103, -119, -85, -51, -17 }),
                 createPrimitive("PropertyBoolean", true),
@@ -549,22 +575,26 @@ public class DataCreator {
                 createPrimitive("PropertySByte", Byte.MAX_VALUE),
                 createPrimitive("PropertyTimeOfDay", getTime(21, 5, 59)))))
         .addProperty(createComplex("PropertyCompNav",
+            ComplexTypeProvider.nameCTBasePrimCompNav.getFullQualifiedNameAsString(),
             createPrimitive("PropertyInt16", (short) 1),
             createKeyNavAllPrimComplexValue("PropertyComp")))
-        .addProperty(createComplexCollection("CollPropertyComp"))
+        .addProperty(createComplexCollection("CollPropertyComp", null))
         .addProperty(createComplexCollection("CollPropertyCompNav",
+            ComplexTypeProvider.nameCTNavFiveProp.getFullQualifiedNameAsString(),
             Arrays.asList(
                 createPrimitive("PropertyInt16", (short) 1))))
         .addProperty(createPrimitiveCollection("CollPropertyString",
             "1",
             "2"))
         .addProperty(createComplex("PropertyCompTwoPrim",
+            ComplexTypeProvider.nameCTTwoPrim.getFullQualifiedNameAsString(),
             createPrimitive("PropertyInt16", (short) 11),
             createPrimitive("PropertyString", "11")));
   }
 
   protected Property createKeyNavAllPrimComplexValue(final String name) {
     return createComplex(name,
+        ComplexTypeProvider.nameCTAllPrim.getFullQualifiedNameAsString(),
         createPrimitive("PropertyString", "First Resource - positive values"),
         createPrimitive("PropertyBinary", new byte[] { 1, 35, 69, 103, -119, -85, -51, -17 }),
         createPrimitive("PropertyBoolean", true),
@@ -588,7 +618,9 @@ public class DataCreator {
     entityCollection.getEntities().add(new Entity()
         .addProperty(createPrimitive("PropertyInt16", Short.MAX_VALUE))
         .addProperty(createComplex("PropertyComp",
+            ComplexTypeProvider.nameCTCompCollComp.getFullQualifiedNameAsString(),
             createComplexCollection("CollPropertyComp",
+                ComplexTypeProvider.nameCTCompCollComp.getFullQualifiedNameAsString(),
                 Arrays.asList(
                     createPrimitive("PropertyInt16", (short) 555),
                     createPrimitive("PropertyString", "1 Test Complex in Complex Property")),
@@ -602,7 +634,9 @@ public class DataCreator {
     entityCollection.getEntities().add(new Entity()
         .addProperty(createPrimitive("PropertyInt16", 12345))
         .addProperty(createComplex("PropertyComp",
+            ComplexTypeProvider.nameCTCompCollComp.getFullQualifiedNameAsString(),
             createComplexCollection("CollPropertyComp",
+                ComplexTypeProvider.nameCTCompCollComp.getFullQualifiedNameAsString(),
                 Arrays.asList(
                     createPrimitive("PropertyInt16", (short) 888),
                     createPrimitive("PropertyString", "11 Test Complex in Complex Property")),
@@ -615,7 +649,7 @@ public class DataCreator {
 
     setEntityType(entityCollection, edm.getEntityType(EntityTypeProvider.nameETCompCollComp));
     createEntityId(edm, odata, "ESCompCollComp", entityCollection);
-
+    createOperations("ESCompCollComp", entityCollection, EntityTypeProvider.nameETCompCollComp);
     return entityCollection;
   }
 
@@ -640,6 +674,7 @@ public class DataCreator {
 
     setEntityType(entityCollection, edm.getEntityType(EntityTypeProvider.nameETTwoPrim));
     createEntityId(edm, odata, "ESTwoPrim", entityCollection);
+    createOperations("ESTwoPrim", entityCollection, EntityTypeProvider.nameETTwoPrim);
     return entityCollection;
   }
 
@@ -710,16 +745,92 @@ public class DataCreator {
 
     setEntityType(entityCollection, edm.getEntityType(EntityTypeProvider.nameETAllPrim));
     createEntityId(edm, odata, "ESAllPrim", entityCollection);
-
+    createOperations("ESAllPrim", entityCollection, EntityTypeProvider.nameETAllPrim);
     return entityCollection;
   }
 
+  private void createOperations(String entitySetName,
+      EntityCollection entityCollection, FullQualifiedName entityTypeName) {
+    try {
+      List<CsdlAction> actions = ActionProvider.getBoundActionsForEntityType(entityTypeName);
+      for (CsdlAction action : actions) {
+        if (action.getParameters().get(0).isCollection()) {
+          Operation operation = buildOperation(action, entitySetName);
+          entityCollection.getOperations().add(operation);          
+        } else {
+          for (Entity entity:entityCollection.getEntities()) {
+            Operation operation = buildOperation(action, entity.getId().toASCIIString());
+            entity.getOperations().add(operation);
+          }
+        }
+      }
+      
+      List<CsdlFunction> functions = FunctionProvider.getBoundFunctionsForType(entityTypeName);
+      for (CsdlFunction func : functions) {
+        if (func.getParameters().get(0).isCollection()) {
+          Operation operation = buildOperation(func, entitySetName);
+          entityCollection.getOperations().add(operation);          
+        } else {
+          for (Entity entity:entityCollection.getEntities()) {
+            Operation operation = buildOperation(func, entity.getId().toASCIIString());
+            entity.getOperations().add(operation);
+          }
+        }
+      }
+    } catch (ODataException e) {
+      e.printStackTrace();
+    }
+  }
+
+  private static Operation buildOperation(CsdlFunction function, String id) {
+    String fqn = SchemaProvider.NAMESPACE+"."+function.getName();
+    Operation operation = new Operation();          
+    operation.setType(Operation.Type.FUNCTION);
+    operation.setTitle(fqn);
+    StringBuilder params = new StringBuilder();
+    StringBuilder nameFQN = new StringBuilder();
+    params.append(fqn);
+    nameFQN.append(fqn);
+    if (!function.getParameters().isEmpty() && function.getParameters().size() > 1) {
+      params.append("(");
+      nameFQN.append("(");
+      boolean first = true;
+      for (int i = 1; i < function.getParameters().size(); i++) {
+        CsdlParameter p = function.getParameters().get(i);
+        if (first) {
+          first = false;
+        } else {
+          params.append(",");
+          nameFQN.append(",");                
+        }
+        params.append(p.getName()).append("=").append("@").append(p.getName());
+        nameFQN.append(p.getName());
+      }            
+      params.append(")");
+      nameFQN.append(")");
+    }
+    operation.setMetadataAnchor("#"+nameFQN);
+    operation.setTarget(URI.create(id+"/"+params.toString()));
+    return operation;
+  }
+
+  private Operation buildOperation(CsdlAction action, String id) {
+    String fqn = SchemaProvider.NAMESPACE+"."+action.getName();
+    Operation operation = new Operation();
+    operation.setMetadataAnchor("#"+fqn);
+    operation.setType(Operation.Type.ACTION);
+    operation.setTitle(fqn);
+    operation.setTarget(URI.create(id+"/"+fqn));
+    return operation;
+  }
+
   private EntityCollection createESCompAllPrim(final Edm edm, final OData odata) {
     EntityCollection entityCollection = new EntityCollection();
 
     Entity entity = new Entity()
         .addProperty(createPrimitive("PropertyInt16", Short.MAX_VALUE))
         .addProperty(createComplex("PropertyComp",
+            ComplexTypeProvider.nameCTAllPrim.getFullQualifiedNameAsString(),
             createPrimitive("PropertyString", "First Resource - first"),
             createPrimitive("PropertyBinary",
                 new byte[] { 0x01, 0x23, 0x45, 0x67, (byte) 0x89, (byte) 0xAB, (byte) 0xCD, (byte) 0xEF }),
@@ -743,6 +854,7 @@ public class DataCreator {
     entity = new Entity()
         .addProperty(createPrimitive("PropertyInt16", (short) 7))
         .addProperty(createComplex("PropertyComp",
+            ComplexTypeProvider.nameCTAllPrim.getFullQualifiedNameAsString(),
             createPrimitive("PropertyString", "Second Resource - second"),
             createPrimitive("PropertyBinary",
                 new byte[] { 0x01, 0x23, 0x45, 0x67, (byte) 0x89, (byte) 0xAB, (byte) 0xCD, (byte) 0xEF }),
@@ -766,6 +878,7 @@ public class DataCreator {
     entity = new Entity()
         .addProperty(createPrimitive("PropertyInt16", (short) 0))
         .addProperty(createComplex("PropertyComp",
+            ComplexTypeProvider.nameCTAllPrim.getFullQualifiedNameAsString(),
             createPrimitive("PropertyString", "Third Resource - third"),
             createPrimitive("PropertyBinary",
                 new byte[] { 0x01, 0x23, 0x45, 0x67, (byte) 0x89, (byte) 0xAB, (byte) 0xCD, (byte) 0xEF }),
@@ -789,6 +902,7 @@ public class DataCreator {
     entity = new Entity()
         .addProperty(createPrimitive("PropertyInt16", (short) -32768))
         .addProperty(createComplex("PropertyComp",
+            ComplexTypeProvider.nameCTAllPrim.getFullQualifiedNameAsString(),
             createPrimitive("PropertyString", null),
             createPrimitive("PropertyBinary", null),
             createPrimitive("PropertyBoolean", null),
@@ -810,7 +924,7 @@ public class DataCreator {
 
     setEntityType(entityCollection, edm.getEntityType(EntityTypeProvider.nameETCompAllPrim));
     createEntityId(edm, odata, "ESCompAllPrim", entityCollection);
-
+    createOperations("ESCompAllPrim", entityCollection, EntityTypeProvider.nameETCompAllPrim);
     return entityCollection;
   }
 
@@ -823,7 +937,7 @@ public class DataCreator {
 
     setEntityType(entityCollection, edm.getEntityType(EntityTypeProvider.nameETCollAllPrim));
     createEntityId(edm, odata, "ESCollAllPrim", entityCollection);
-
+    createOperations("ESCollAllPrim", entityCollection, EntityTypeProvider.nameETCollAllPrim);
     return entityCollection;
   }
 
@@ -906,6 +1020,7 @@ public class DataCreator {
             "Employee2@company.example",
             "Employee3@company.example"))
         .addProperty(createComplex("PropertyComp",
+            ComplexTypeProvider.nameCTTwoPrim.getFullQualifiedNameAsString(),
             createPrimitive("PropertyInt16", (short) 111),
             createPrimitive("PropertyString", "TEST A")))
         .addProperty(createCollPropertyComp()));
@@ -917,6 +1032,7 @@ public class DataCreator {
             "Employee2@company.example",
             "Employee3@company.example"))
         .addProperty(createComplex("PropertyComp",
+            ComplexTypeProvider.nameCTTwoPrim.getFullQualifiedNameAsString(),
             createPrimitive("PropertyInt16", (short) 222),
             createPrimitive("PropertyString", "TEST B")))
         .addProperty(createCollPropertyComp()));
@@ -928,13 +1044,14 @@ public class DataCreator {
             "Employee2@company.example",
             "Employee3@company.example"))
         .addProperty(createComplex("PropertyComp",
+            ComplexTypeProvider.nameCTTwoPrim.getFullQualifiedNameAsString(),
             createPrimitive("PropertyInt16", (short) 333),
             createPrimitive("PropertyString", "TEST C")))
         .addProperty(createCollPropertyComp()));
 
     setEntityType(entityCollection, edm.getEntityType(EntityTypeProvider.nameETMixPrimCollComp));
     createEntityId(edm, odata, "ESMixPrimCollComp", entityCollection);
-
+    createOperations("ESMixPrimCollComp", entityCollection, EntityTypeProvider.nameETMixPrimCollComp);
     return entityCollection;
   }
 
@@ -948,6 +1065,7 @@ public class DataCreator {
             "Streamed-Employee2@company.example",
             "Streamed-Employee3@company.example"))
         .addProperty(createComplex("PropertyComp",
+            null,
             createPrimitive("PropertyInt16", (short) 111),
             createPrimitive("PropertyString", "TEST A")))
         .addProperty(createCollPropertyComp()));
@@ -959,6 +1077,7 @@ public class DataCreator {
             "Streamed-Employee2@company.example",
             "Streamed-Employee3@company.example"))
         .addProperty(createComplex("PropertyComp",
+            null,
             createPrimitive("PropertyInt16", (short) 222),
             createPrimitive("PropertyString", "TEST B")))
         .addProperty(createCollPropertyComp()));
@@ -970,19 +1089,48 @@ public class DataCreator {
             "Streamed-Employee2@company.example",
             "Streamed-Employee3@company.example"))
         .addProperty(createComplex("PropertyComp",
+            null,
             createPrimitive("PropertyInt16", (short) 333),
             createPrimitive("PropertyString", "TEST C")))
         .addProperty(createCollPropertyComp()));
 
     setEntityType(entityCollection, edm.getEntityType(EntityTypeProvider.nameETMixPrimCollComp));
     createEntityId(edm, odata, "ESStream", entityCollection);
-
+    createOperations("ESStream", entityCollection, EntityTypeProvider.nameETMixPrimCollComp);
     return entityCollection;
   }
 
+  private EntityCollection createESWithStream(final Edm edm, final OData odata) {
+    EntityCollection entityCollection = new EntityCollection();
+
+    Link readLink = new Link();
+    readLink.setRel(Constants.NS_MEDIA_READ_LINK_REL);
+    readLink.setHref("readLink");
+    
+    entityCollection.getEntities().add(new Entity()
+        .addProperty(createPrimitive("PropertyInt16", Short.MAX_VALUE))
+        .addProperty(new Property(null, "PropertyStream", ValueType.PRIMITIVE, readLink)));
+
+    Link editLink = new Link();
+    editLink.setRel(Constants.NS_MEDIA_EDIT_LINK_REL);
+    editLink.setHref("http://mediaserver:1234/editLink");
+    editLink.setMediaETag("eTag");
+    editLink.setType("image/jpeg");
+
+    entityCollection.getEntities().add(new Entity()
+        .addProperty(createPrimitive("PropertyInt16", (short) 7))
+        .addProperty(new Property(null, "PropertyStream", ValueType.PRIMITIVE, editLink)));
+
+    setEntityType(entityCollection, edm.getEntityType(EntityTypeProvider.nameETStream));
+    createEntityId(edm, odata, "ESWithStream", entityCollection);
+    createOperations("ESWithStream", entityCollection, EntityTypeProvider.nameETStream);
+    return entityCollection;
+  }
+  
   @SuppressWarnings("unchecked")
   private Property createCollPropertyComp() {
     return createComplexCollection("CollPropertyComp",
+        ComplexTypeProvider.nameCTTwoPrim.getFullQualifiedNameAsString(),
         Arrays.asList(
             createPrimitive("PropertyInt16", (short) 123),
             createPrimitive("PropertyString", "TEST 1")),
@@ -1029,7 +1177,7 @@ public class DataCreator {
 
     setEntityType(entityCollection, edm.getEntityType(EntityTypeProvider.nameETAllKey));
     createEntityId(edm, odata, "ESAllKey", entityCollection);
-
+    createOperations( "ESAllKey", entityCollection, EntityTypeProvider.nameETAllKey);
     return entityCollection;
   }
 
@@ -1039,7 +1187,9 @@ public class DataCreator {
     Entity entity = new Entity();
     entity.addProperty(createPrimitive("PropertyInt16", (short) 1));
     entity.addProperty(createComplex("PropertyComp",
+        ComplexTypeProvider.nameCTCompComp.getFullQualifiedNameAsString(),
         createComplex("PropertyComp",
+            ComplexTypeProvider.nameCTTwoPrim.getFullQualifiedNameAsString(),
             createPrimitive("PropertyInt16", (short) 123),
             createPrimitive("PropertyString", "String 1"))));
     entityCollection.getEntities().add(entity);
@@ -1048,7 +1198,8 @@ public class DataCreator {
     entity.addProperty(createPrimitive("PropertyInt16", (short) 2));
     entity.addProperty(createComplex("PropertyComp", 
         ComplexTypeProvider.nameCTCompCompExtended.getFullQualifiedNameAsString(), 
-        createComplex("PropertyComp",  
+        createComplex("PropertyComp",
+            ComplexTypeProvider.nameCTTwoPrim.getFullQualifiedNameAsString(),
             createPrimitive("PropertyInt16", (short) 987),
             createPrimitive("PropertyString", "String 2")),
         createPrimitive("PropertyDate", getDate(2012, 12, 3))));
@@ -1056,7 +1207,7 @@ public class DataCreator {
 
     setEntityType(entityCollection, edm.getEntityType(EntityTypeProvider.nameETCompComp));
     createEntityId(edm, odata, "ESCompComp", entityCollection);
-
+    createOperations("ESCompComp", entityCollection, EntityTypeProvider.nameETCompComp);
     return entityCollection;
   }
 
@@ -1097,7 +1248,7 @@ public class DataCreator {
 
     setEntityType(entityCollection, edm.getEntityType(EntityTypeProvider.nameETMedia));
     createEntityId(edm, odata, "ESMedia", entityCollection);
-
+    createOperations("ESMedia", entityCollection, EntityTypeProvider.nameETMedia);
     return entityCollection;
   }
 
@@ -1211,31 +1362,48 @@ public class DataCreator {
     }
     return new Property(null, name, ValueType.COLLECTION_PRIMITIVE, propertyValues);
   }
-
-  protected static Property createComplex(final String name, final Property... properties) {
-    ComplexValue complexValue = new ComplexValue();
-    for (final Property property : properties) {
-      complexValue.getValue().add(property);
-    }
-    return new Property(null, name, ValueType.COMPLEX, complexValue);
-  }
   
   protected static Property createComplex(final String name, final String type, final Property... properties) {
     ComplexValue complexValue = new ComplexValue();
     for (final Property property : properties) {
       complexValue.getValue().add(property);
     }
-    return new Property(type, name, ValueType.COMPLEX, complexValue);
+    Property property = new Property(type, name, ValueType.COMPLEX, complexValue);
+    createOperations(name, type, property);
+    return property;
+  }
+
+  private static void createOperations(final String name, final String type,
+      Property property) {
+    if (type != null) {
+      try {
+        List<CsdlFunction> functions = FunctionProvider.getBoundFunctionsForType(new FullQualifiedName(type));
+        for (CsdlFunction func : functions) {
+          if (func.getParameters().get(0).isCollection() && property.isCollection()) {
+            Operation operation = buildOperation(func, name);
+            property.getOperations().add(operation);          
+          } else {
+            Operation operation = buildOperation(func, name);
+            property.getOperations().add(operation);
+          }
+        }        
+      } catch (ODataException e) {
+        // ignore
+      }
+    }
   }  
 
-  protected static Property createComplexCollection(final String name, final List<Property>... propertiesList) {
+  protected static Property createComplexCollection(final String name,
+      String type, final List<Property>... propertiesList) {
     List<ComplexValue> complexCollection = new ArrayList<ComplexValue>();
     for (final List<Property> properties : propertiesList) {
       ComplexValue complexValue = new ComplexValue();
       complexValue.getValue().addAll(properties);
       complexCollection.add(complexValue);
     }
-    return new Property(null, name, ValueType.COLLECTION_COMPLEX, complexCollection);
+    Property property =  new Property(type, name, ValueType.COLLECTION_COMPLEX, complexCollection);
+    createOperations(name, type, property);
+    return property;
   }
 
   private static Calendar getDateTime(final int year, final int month, final int day,

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/eaceb01d/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataProvider.java
----------------------------------------------------------------------
diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataProvider.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataProvider.java
index 9dad2b9..da5da65 100644
--- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataProvider.java
+++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataProvider.java
@@ -267,10 +267,12 @@ public class DataProvider {
     } else {
       if (edmProperty.isCollection()) {
         @SuppressWarnings("unchecked")
-        Property newProperty2 = DataCreator.createComplexCollection(propertyName);
+        Property newProperty2 = DataCreator.createComplexCollection(propertyName, 
+            edmProperty.getType().getFullQualifiedName().getFullQualifiedNameAsString());
         newProperty = newProperty2;
       } else {
-        newProperty = DataCreator.createComplex(propertyName);
+        newProperty = DataCreator.createComplex(propertyName,
+            edmProperty.getType().getFullQualifiedName().getFullQualifiedNameAsString());
         createProperties((EdmComplexType) type, newProperty.asComplex().getValue());
       }
     }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/eaceb01d/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/FunctionData.java
----------------------------------------------------------------------
diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/FunctionData.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/FunctionData.java
index e31ff80..ef1fa70 100644
--- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/FunctionData.java
+++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/FunctionData.java
@@ -31,6 +31,7 @@ import org.apache.olingo.commons.api.data.Property;
 import org.apache.olingo.commons.api.data.ValueType;
 import org.apache.olingo.commons.api.http.HttpStatusCode;
 import org.apache.olingo.server.tecsvc.data.DataProvider.DataProviderException;
+import org.apache.olingo.server.tecsvc.provider.ComplexTypeProvider;
 
 public class FunctionData {
 
@@ -100,14 +101,17 @@ public class FunctionData {
       return data.get("ESCollAllPrim").getEntities().get(0).getProperty("CollPropertyString");
     } else if (name.equals("UFCRTCTTwoPrim")) {
       return DataCreator.createComplex(name,
+          ComplexTypeProvider.nameCTTwoPrim.getFullQualifiedNameAsString(),
           DataCreator.createPrimitive("PropertyInt16", (short) 16),
           DataCreator.createPrimitive("PropertyString", "UFCRTCTTwoPrim string value"));
     } else if (name.equals("UFCRTCTTwoPrimParam")) {
       return DataCreator.createComplex(name,
+          ComplexTypeProvider.nameCTTwoPrim.getFullQualifiedNameAsString(),
           DataCreator.createPrimitive("PropertyInt16", getParameterInt16(parameters)),
           DataCreator.createPrimitive("PropertyString", getParameterString(parameters)));
     } else if (name.equals("UFCRTCollCTTwoPrim")) {
       return DataCreator.createComplexCollection(name,
+          ComplexTypeProvider.nameCTTwoPrim.getFullQualifiedNameAsString(),
           Arrays.asList(DataCreator.createPrimitive("PropertyInt16", (short) 16),
               DataCreator.createPrimitive("PropertyString", "Test123")),
           Arrays.asList(DataCreator.createPrimitive("PropertyInt16", 17),
@@ -138,6 +142,7 @@ public class FunctionData {
       final String parameterString = getParameterString(parameters);
       if (parameterString == null) {
         return DataCreator.createComplexCollection(name,
+            ComplexTypeProvider.nameCTTwoPrim.getFullQualifiedNameAsString(),
             Arrays.asList(DataCreator.createPrimitive("PropertyInt16", 1),
                 DataCreator.createPrimitive("PropertyString", name + " int16 value: " + parameterInt16)),
             Arrays.asList(DataCreator.createPrimitive("PropertyInt16", 2),

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/eaceb01d/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalEntityProcessor.java
----------------------------------------------------------------------
diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalEntityProcessor.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalEntityProcessor.java
index c59f3ef..c547992 100644
--- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalEntityProcessor.java
+++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalEntityProcessor.java
@@ -30,6 +30,7 @@ import org.apache.olingo.commons.api.data.ContextURL.Suffix;
 import org.apache.olingo.commons.api.data.Entity;
 import org.apache.olingo.commons.api.data.EntityCollection;
 import org.apache.olingo.commons.api.data.EntityIterator;
+import org.apache.olingo.commons.api.data.Operation;
 import org.apache.olingo.commons.api.data.Property;
 import org.apache.olingo.commons.api.data.ValueType;
 import org.apache.olingo.commons.api.edm.EdmEntitySet;
@@ -488,6 +489,7 @@ public class TechnicalEntityProcessor extends TechnicalProcessor
     // copy of the entity set (new EntitySet, but exactly the same data).
     EntityCollection entitySet = new EntityCollection();
     entitySet.getEntities().addAll(entitySetInitial.getEntities());
+    entitySet.getOperations().addAll(entitySetInitial.getOperations());
 
     // Apply system query options.
     SearchHandler.applySearchSystemQueryOption(uriInfo.getSearchOption(), entitySet);
@@ -599,6 +601,11 @@ public class TechnicalEntityProcessor extends TechnicalProcessor
       Iterator<Entity> entityIterator = entityCollection.iterator();
 
       @Override
+      public List<Operation> getOperations() {
+        return entityCollection.getOperations();
+      } 
+      
+      @Override
       public boolean hasNext() {
         return entityIterator.hasNext();
       }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/eaceb01d/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/ExpandSystemQueryOptionHandler.java
----------------------------------------------------------------------
diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/ExpandSystemQueryOptionHandler.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/ExpandSystemQueryOptionHandler.java
index f3d707a..7ddad53 100644
--- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/ExpandSystemQueryOptionHandler.java
+++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/ExpandSystemQueryOptionHandler.java
@@ -196,7 +196,7 @@ public class ExpandSystemQueryOptionHandler {
     newEntitySet.setNext(entitySet.getNext());
     newEntitySet.setId(entitySet.getId());
     newEntitySet.setBaseURI(entitySet.getBaseURI());
-
+    newEntitySet.getOperations().addAll(entitySet.getOperations());
     return newEntitySet;
   }
 

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/eaceb01d/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/ActionProvider.java
----------------------------------------------------------------------
diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/ActionProvider.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/ActionProvider.java
index c62b5d7..39244b3 100644
--- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/ActionProvider.java
+++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/ActionProvider.java
@@ -18,6 +18,7 @@
  */
 package org.apache.olingo.server.tecsvc.provider;
 
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
@@ -79,8 +80,27 @@ public class ActionProvider {
       new FullQualifiedName(SchemaProvider.NAMESPACE, "UARTTwoParam");
   public static final FullQualifiedName nameUARTByteNineParam =
       new FullQualifiedName(SchemaProvider.NAMESPACE, "UARTByteNineParam");
+  
+  public static List<CsdlAction> getBoundActionsForEntityType(FullQualifiedName entityType) throws ODataException {
+    FullQualifiedName[] actionNames = {nameBAESAllPrimRTETAllPrim, 
+        nameBAESTwoKeyNavRTESTwoKeyNav, nameBAESTwoKeyNavRTESKeyNav, nameBAETBaseTwoKeyNavRTETBaseTwoKeyNav,
+        nameBAETTwoBaseTwoKeyNavRTETBaseTwoKeyNav,nameBAETTwoKeyNavRTETTwoKeyNav,
+        nameBAESAllPrimRT,nameBAETAllPrimRT};
+    
+    List<CsdlAction> actions = new ArrayList<CsdlAction>();
+    for (FullQualifiedName fqn:actionNames) {
+      List<CsdlAction> entityActions = getActions(fqn);
+      for (CsdlAction action:entityActions) {
+        CsdlParameter parameter = action.getParameters().get(0);
+        if (parameter.getTypeFQN().equals(entityType)) {
+          actions.add(action);
+        }
+      }
+    }
+    return actions;
+  }
 
-  public List<CsdlAction> getActions(final FullQualifiedName actionName) throws ODataException {
+  public static List<CsdlAction> getActions(final FullQualifiedName actionName) throws ODataException {
     if (actionName.equals(nameUARTString)) {
       return Collections.singletonList(
           new CsdlAction().setName(nameUARTString.getName())

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/eaceb01d/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/ContainerProvider.java
----------------------------------------------------------------------
diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/ContainerProvider.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/ContainerProvider.java
index 9f06b89..8dd07a8 100644
--- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/ContainerProvider.java
+++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/ContainerProvider.java
@@ -102,6 +102,7 @@ public class ContainerProvider {
     entitySets.add(prov.getEntitySet(ContainerProvider.nameContainer, "ESTwoBaseTwoKeyNav"));
     entitySets.add(prov.getEntitySet(ContainerProvider.nameContainer, "ESKeyNavCont"));
     entitySets.add(prov.getEntitySet(ContainerProvider.nameContainer, "ESTwoKeyNavCont"));
+    entitySets.add(prov.getEntitySet(ContainerProvider.nameContainer, "ESWithStream"));
     entitySets.add(prov.getEntitySet(ContainerProvider.nameContainer, ES_STREAM));
 
     // Singletons
@@ -647,6 +648,10 @@ public class ContainerProvider {
                             "type primitive, collection of primitive, complex and collection of complex")),
                 new CsdlAnnotation().setTerm(TermProvider.TERM_DATA.getFullQualifiedNameAsString()).setExpression(
                     new CsdlConstantExpression(CsdlConstantExpression.ConstantExpressionType.Bool, "true"))));
+      } else if (name.equals("ESWithStream")) {
+        return new CsdlEntitySet()
+            .setName("ESWithStream")
+            .setType(EntityTypeProvider.nameETStream);        
       }
     }
 

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/eaceb01d/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/EntityTypeProvider.java
----------------------------------------------------------------------
diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/EntityTypeProvider.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/EntityTypeProvider.java
index c2397c4..10f3971 100644
--- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/EntityTypeProvider.java
+++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/EntityTypeProvider.java
@@ -84,6 +84,9 @@ public class EntityTypeProvider {
 
   public static final FullQualifiedName nameETMixEnumDefCollComp = new FullQualifiedName(SchemaProvider.NAMESPACE,
       "ETMixEnumDefCollComp");
+  public static final FullQualifiedName nameETStream = new FullQualifiedName(SchemaProvider.NAMESPACE,
+      "ETWithStream");
+  
 
   public CsdlEntityType getEntityType(final FullQualifiedName entityTypeName) throws ODataException {
     if (entityTypeName.equals(nameETAllPrim)) {
@@ -469,8 +472,16 @@ public class EntityTypeProvider {
               PropertyProvider.collPropertyTypeDefinition_TDString,
               PropertyProvider.propertyComp_CTMixEnumTypeDefColl,
               PropertyProvider.propertyCompColl_CTMixEnumTypeDefColl));
+    } else if (entityTypeName.equals(nameETStream)) {
+      return new CsdlEntityType()
+          .setName(nameETStream.getName())
+          .setKey(Arrays.asList(
+              new CsdlPropertyRef()
+                  .setName("PropertyInt16")))
+          .setProperties(Arrays.asList(
+              PropertyProvider.propertyInt16_NotNullable,
+              PropertyProvider.propertyStream));      
     }
-
     return null;
   }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/eaceb01d/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/FunctionProvider.java
----------------------------------------------------------------------
diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/FunctionProvider.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/FunctionProvider.java
index b60b954..69d179d 100644
--- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/FunctionProvider.java
+++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/FunctionProvider.java
@@ -18,6 +18,7 @@
  */
 package org.apache.olingo.server.tecsvc.provider;
 
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
@@ -31,6 +32,11 @@ import org.apache.olingo.commons.api.ex.ODataException;
 public class FunctionProvider {
 
   // Bound Functions
+  
+  
+  public static final FullQualifiedName nameBFCColCTAllPrimRTESAllPrim =
+    new FullQualifiedName(SchemaProvider.NAMESPACE, "BFCColCTAllPrimRTESAllPrim");
+
   public static final FullQualifiedName nameBFCCollCTPrimCompRTESAllPrim =
       new FullQualifiedName(SchemaProvider.NAMESPACE, "BFCCollCTPrimCompRTESAllPrim");
 
@@ -181,7 +187,56 @@ public class FunctionProvider {
   public static final FullQualifiedName nameUFNRTByteNineParam =
       new FullQualifiedName(SchemaProvider.NAMESPACE, "UFNRTByteNineParam");
 
-  public List<CsdlFunction> getFunctions(final FullQualifiedName functionName) throws ODataException {
+  
+  public static List<CsdlFunction> getBoundFunctionsForType(FullQualifiedName entityType) throws ODataException {
+    FullQualifiedName[] funcNames = {
+        nameBFCColCTAllPrimRTESAllPrim,
+        nameBFCCollCTPrimCompRTESAllPrim, 
+        nameBFCCollStringRTESTwoKeyNav,
+        nameBFCCTPrimCompRTESBaseTwoKeyNav,
+        nameBFCCTPrimCompRTESTwoKeyNav,
+        nameBFCCTPrimCompRTESTwoKeyNavParam,
+        nameBFCCTPrimCompRTETTwoKeyNavParam,
+        nameBFNESAllPrimRTCTAllPrim,
+        nameBFCESBaseTwoKeyNavRTESBaseTwoKey,
+        nameBFCESKeyNavRTETKeyNav,
+        nameBFCESKeyNavRTETKeyNavParam,
+        nameBFCESTwoKeyNavRTCollCTTwoPrim,
+        nameBFCESTwoKeyNavRTCollString,
+        nameBFCESTwoKeyNavRTCTTwoPrim,
+        nameBFCESTwoKeyNavRTESTwoKeyNav,
+        nameBFCESTwoKeyNavRTString,
+        nameBFCESTwoKeyNavRTStringParam,
+        nameBFCESTwoKeyNavRTTwoKeyNav,
+        nameBFCETBaseTwoKeyNavRTESBaseTwoKey,
+        nameBFCETBaseTwoKeyNavRTESTwoKeyNav,
+        nameBFCETBaseTwoKeyNavRTETTwoKeyNav,
+        nameBFCETKeyNavRTETKeyNav,
+        nameBFCETTwoKeyNavRTCTTwoPrim,
+        nameBFCETTwoKeyNavRTESTwoKeyNav,
+        nameBFCETTwoKeyNavRTETTwoKeyNav,
+        nameBFCSINavRTESTwoKeyNav,
+        nameBFCStringRTESTwoKeyNav,
+        nameBFESTwoKeyNavRTESTwoKeyNav,
+        nameBFCESTwoKeyNavRTCTNavFiveProp,
+        nameBFCESTwoKeyNavRTCollCTNavFiveProp,
+        nameBFCESKeyNavRTESTwoKeyNav
+    };
+    
+    List<CsdlFunction> functions = new ArrayList<CsdlFunction>();
+    for (FullQualifiedName fqn:funcNames) {
+      List<CsdlFunction> entityFuncs = getFunctions(fqn);
+      for (CsdlFunction func:entityFuncs) {
+        CsdlParameter parameter = func.getParameters().get(0);
+        if (parameter.getTypeFQN().equals(entityType)) {
+          functions.add(func);
+        }
+      }
+    }
+    return functions;
+  }
+  
+  public static List<CsdlFunction> getFunctions(final FullQualifiedName functionName) throws ODataException {
 
     if (functionName.equals(nameUFNRTInt16)) {
       return Collections.singletonList(
@@ -564,7 +619,7 @@ public class FunctionProvider {
                       .setNullable(false)));
 
     } else if (functionName.equals(nameBFNESAllPrimRTCTAllPrim)) {
-      return Collections.singletonList(
+      return Arrays.asList(
           new CsdlFunction()
               .setName("BFNESAllPrimRTCTAllPrim")
               .setBound(true)
@@ -573,7 +628,19 @@ public class FunctionProvider {
                       .setCollection(true).setNullable(false)))
               .setComposable(false)
               .setReturnType(
-                  new CsdlReturnType().setType(ComplexTypeProvider.nameCTAllPrim).setNullable(false)));
+                  new CsdlReturnType().setType(ComplexTypeProvider.nameCTAllPrim).setNullable(false)),
+              new CsdlFunction()
+              .setName("BFNESAllPrimRTCTAllPrim")
+              .setBound(true)
+              .setParameters(Arrays.asList(
+                  new CsdlParameter().setName("BindingParam").setType(EntityTypeProvider.nameETAllPrim)
+                      .setCollection(true).setNullable(false),
+                  new CsdlParameter().setName("Param2").setType(PropertyProvider.nameInt16)
+                  .setCollection(true).setNullable(false)))
+              .setComposable(false)
+              .setReturnType(
+                  new CsdlReturnType().setType(ComplexTypeProvider.nameCTAllPrim).setNullable(false))              
+          );
 
     } else if (functionName.equals(nameBFCESTwoKeyNavRTCTTwoPrim)) {
       return Collections.singletonList(
@@ -716,6 +783,19 @@ public class FunctionProvider {
                   new CsdlReturnType().setType(EntityTypeProvider.nameETBaseTwoKeyNav).setCollection(true)
                       .setNullable(false)));
 
+    } else if (functionName.equals(nameBFCColCTAllPrimRTESAllPrim)) {
+      return Collections.singletonList(
+          new CsdlFunction()
+              .setName("BFCColCTAllPrimRTESAllPrim")
+              .setBound(true)
+              .setParameters(Collections.singletonList(
+                  new CsdlParameter().setName("BindingParam").setType(ComplexTypeProvider.nameCTAllPrim)
+                      .setNullable(false)))
+              .setComposable(true)
+              .setReturnType(
+                  new CsdlReturnType().setType(EntityTypeProvider.nameETAllPrim).setCollection(true)
+                      .setNullable(false)));
+
     } else if (functionName.equals(nameBFCCollCTPrimCompRTESAllPrim)) {
       return Collections.singletonList(
           new CsdlFunction()

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/eaceb01d/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/PropertyProvider.java
----------------------------------------------------------------------
diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/PropertyProvider.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/PropertyProvider.java
index c163d59..42e253d 100644
--- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/PropertyProvider.java
+++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/PropertyProvider.java
@@ -48,6 +48,7 @@ public class PropertyProvider {
 
   public static final FullQualifiedName nameString = EdmPrimitiveTypeKind.String.getFullQualifiedName();
   public static final FullQualifiedName nameTimeOfDay = EdmPrimitiveTypeKind.TimeOfDay.getFullQualifiedName();
+  public static final FullQualifiedName nameStream = EdmPrimitiveTypeKind.Stream.getFullQualifiedName();
 
   // Primitive Properties --------------------------------------------------------------------------------------------
   public static final CsdlProperty collPropertyBinary = new CsdlProperty()
@@ -563,6 +564,11 @@ public class PropertyProvider {
       .setType(nameTimeOfDay)
       .setNullable(true);
 
+  public static final CsdlProperty propertyStream = new CsdlProperty()
+      .setName("PropertyStream")
+      .setType(nameStream)
+      .setNullable(true);
+  
   // Complex Properties ----------------------------------------------------------------------------------------------
   public static final CsdlProperty collPropertyComp_CTPrimComp = new CsdlProperty()
       .setName("CollPropertyComp")

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/eaceb01d/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializerTest.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializerTest.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializerTest.java
index e4f62c2..9540dda 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializerTest.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializerTest.java
@@ -26,6 +26,7 @@ import java.nio.channels.WritableByteChannel;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.Iterator;
+import java.util.List;
 
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.io.output.ByteArrayOutputStream;
@@ -35,6 +36,7 @@ import org.apache.olingo.commons.api.data.ContextURL.Suffix;
 import org.apache.olingo.commons.api.data.Entity;
 import org.apache.olingo.commons.api.data.EntityCollection;
 import org.apache.olingo.commons.api.data.EntityIterator;
+import org.apache.olingo.commons.api.data.Operation;
 import org.apache.olingo.commons.api.data.Property;
 import org.apache.olingo.commons.api.data.ValueType;
 import org.apache.olingo.commons.api.edm.EdmComplexType;
@@ -83,6 +85,7 @@ public class ODataJsonSerializerTest {
   private final DataProvider data = new DataProvider(odata, metadata.getEdm());
   private final ODataSerializer serializer = new ODataJsonSerializer(ContentType.JSON);
   private final ODataSerializer serializerNoMetadata = new ODataJsonSerializer(ContentType.JSON_NO_METADATA);
+  private final ODataSerializer serializerFullMetadata = new ODataJsonSerializer(ContentType.JSON_FULL_METADATA);
   private final ODataSerializer serializerIEEECompatible =
       new ODataJsonSerializer(ContentType.create(ContentType.JSON, ContentType.PARAMETER_IEEE754_COMPATIBLE, "true"));
   private final UriHelper helper = odata.createUriHelper();
@@ -118,7 +121,130 @@ public class ODataJsonSerializerTest {
         + "}";
     Assert.assertEquals(expectedResult, resultString);
   }
+  
+  @Test
+  public void entitySimpleMetadataFull() throws Exception {
+    final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim");
+    final Entity entity = data.readAll(edmEntitySet).getEntities().get(0);
+    InputStream result = serializerFullMetadata.entity(metadata, edmEntitySet.getEntityType(), entity,
+        EntitySerializerOptions.with()
+            .contextURL(ContextURL.with().entitySet(edmEntitySet).suffix(Suffix.ENTITY).build())
+            .build()).getContent();
+    final String resultString = IOUtils.toString(result);
+    final String expected = "{\"@odata.context\":\"$metadata#ESAllPrim/$entity\","
+        + "\"@odata.metadataEtag\":\"W/\\\"metadataETag\\\"\","
+        + "\"@odata.type\":\"#olingo.odata.test1.ETAllPrim\","
+        + "\"@odata.id\":\"ESAllPrim(32767)\","
+        + "\"PropertyInt16@odata.type\":\"#Int16\","
+        + "\"PropertyInt16\":32767,"
+        + "\"PropertyString\":\"First Resource - positive values\","
+        + "\"PropertyBoolean\":true,"
+        + "\"PropertyByte@odata.type\":\"#Byte\","
+        + "\"PropertyByte\":255,"
+        + "\"PropertySByte@odata.type\":\"#SByte\","
+        + "\"PropertySByte\":127,"
+        + "\"PropertyInt32@odata.type\":\"#Int32\","
+        + "\"PropertyInt32\":2147483647,"
+        + "\"PropertyInt64@odata.type\":\"#Int64\","
+        + "\"PropertyInt64\":9223372036854775807,"
+        + "\"PropertySingle@odata.type\":\"#Single\","
+        + "\"PropertySingle\":1.79E20,"
+        + "\"PropertyDouble\":-1.79E19,"
+        + "\"PropertyDecimal@odata.type\":\"#Decimal\","
+        + "\"PropertyDecimal\":34,"
+        + "\"PropertyBinary@odata.type\":\"#Binary\","
+        + "\"PropertyBinary\":\"ASNFZ4mrze8=\","
+        + "\"PropertyDate@odata.type\":\"#Date\","
+        + "\"PropertyDate\":\"2012-12-03\","
+        + "\"PropertyDateTimeOffset@odata.type\":\"#DateTimeOffset\","
+        + "\"PropertyDateTimeOffset\":\"2012-12-03T07:16:23Z\","
+        + "\"PropertyDuration@odata.type\":\"#Duration\","
+        + "\"PropertyDuration\":\"PT6S\","
+        + "\"PropertyGuid@odata.type\":\"#Guid\","
+        + "\"PropertyGuid\":\"01234567-89ab-cdef-0123-456789abcdef\","
+        + "\"PropertyTimeOfDay@odata.type\":\"#TimeOfDay\","
+        + "\"PropertyTimeOfDay\":\"03:26:05\","
+        + "\"NavPropertyETTwoPrimOne@odata.navigationLink\":\"ESTwoPrim(32767)\","
+        + "\"NavPropertyETTwoPrimMany@odata.navigationLink\":\"ESAllPrim(32767)/NavPropertyETTwoPrimMany\","
+        + "\"#olingo.odata.test1.BAETAllPrimRT\":{"
+        +   "\"title\":\"olingo.odata.test1.BAETAllPrimRT\","
+        +   "\"target\":\"ESAllPrim(32767)/olingo.odata.test1.BAETAllPrimRT\""
+        + "}}";        
 
+    Assert.assertEquals(expected, resultString);
+  }
+  
+  @Test
+  public void entitySetMetadataFull() throws Exception {
+    final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim");
+    final EntityCollection entityCol = data.readAll(edmEntitySet);
+    InputStream result = serializerFullMetadata.entityCollection(metadata, edmEntitySet.getEntityType(), entityCol,
+        EntityCollectionSerializerOptions.with()
+            .contextURL(ContextURL.with().entitySet(edmEntitySet).build())
+            .build()).getContent();
+    final String resultString = IOUtils.toString(result);
+    final String expected = "{" + 
+        "\"@odata.context\":\"$metadata#ESAllPrim\"," + 
+        "\"@odata.metadataEtag\":\"W/\\\"metadataETag\\\"\"," + 
+        "\"#olingo.odata.test1.BAESAllPrimRTETAllPrim\":{" + 
+          "\"title\":\"olingo.odata.test1.BAESAllPrimRTETAllPrim\"," + 
+          "\"target\":\"ESAllPrim/olingo.odata.test1.BAESAllPrimRTETAllPrim\"" + 
+        "}," + 
+        "\"#olingo.odata.test1.BAESAllPrimRT\":{" + 
+          "\"title\":\"olingo.odata.test1.BAESAllPrimRT\"," + 
+          "\"target\":\"ESAllPrim/olingo.odata.test1.BAESAllPrimRT\"" + 
+        "}," + 
+        "\"#olingo.odata.test1.BFNESAllPrimRTCTAllPrim\":{" + 
+          "\"title\":\"olingo.odata.test1.BFNESAllPrimRTCTAllPrim\"," + 
+          "\"target\":\"ESAllPrim/olingo.odata.test1.BFNESAllPrimRTCTAllPrim\"" + 
+        "}," + 
+        "\"#olingo.odata.test1.BFNESAllPrimRTCTAllPrim(Param2)\":{" + 
+          "\"title\":\"olingo.odata.test1.BFNESAllPrimRTCTAllPrim\"," + 
+          "\"target\":\"ESAllPrim/olingo.odata.test1.BFNESAllPrimRTCTAllPrim(Param2=@Param2)\"" + 
+        "}," + 
+        "\"value\":[" + 
+          "{" + 
+            "\"@odata.type\":\"#olingo.odata.test1.ETAllPrim\"," + 
+            "\"@odata.id\":\"ESAllPrim(32767)\"," + 
+            "\"PropertyInt16@odata.type\":\"#Int16\"," + 
+            "\"PropertyInt16\":32767," + 
+            "\"PropertyString\":\"First Resource - positive values\"," + 
+            "\"PropertyBoolean\":true," + 
+            "\"PropertyByte@odata.type\":\"#Byte\"," + 
+            "\"PropertyByte\":255," + 
+            "\"PropertySByte@odata.type\":\"#SByte\"," + 
+            "\"PropertySByte\":127," + 
+            "\"PropertyInt32@odata.type\":\"#Int32\"," + 
+            "\"PropertyInt32\":2147483647," + 
+            "\"PropertyInt64@odata.type\":\"#Int64\"," + 
+            "\"PropertyInt64\":9223372036854775807," + 
+            "\"PropertySingle@odata.type\":\"#Single\"," + 
+            "\"PropertySingle\":1.79E20," + 
+            "\"PropertyDouble\":-1.79E19," + 
+            "\"PropertyDecimal@odata.type\":\"#Decimal\"," + 
+            "\"PropertyDecimal\":34," + 
+            "\"PropertyBinary@odata.type\":\"#Binary\"," + 
+            "\"PropertyBinary\":\"ASNFZ4mrze8=\"," + 
+            "\"PropertyDate@odata.type\":\"#Date\"," + 
+            "\"PropertyDate\":\"2012-12-03\"," + 
+            "\"PropertyDateTimeOffset@odata.type\":\"#DateTimeOffset\"," + 
+            "\"PropertyDateTimeOffset\":\"2012-12-03T07:16:23Z\"," + 
+            "\"PropertyDuration@odata.type\":\"#Duration\"," + 
+            "\"PropertyDuration\":\"PT6S\"," + 
+            "\"PropertyGuid@odata.type\":\"#Guid\"," + 
+            "\"PropertyGuid\":\"01234567-89ab-cdef-0123-456789abcdef\"," + 
+            "\"PropertyTimeOfDay@odata.type\":\"#TimeOfDay\"," + 
+            "\"PropertyTimeOfDay\":\"03:26:05\"," + 
+            "\"NavPropertyETTwoPrimOne@odata.navigationLink\":\"ESTwoPrim(32767)\"," + 
+            "\"NavPropertyETTwoPrimMany@odata.navigationLink\":\"ESAllPrim(32767)/NavPropertyETTwoPrimMany\"," + 
+        "\"#olingo.odata.test1.BAETAllPrimRT\":{" + 
+          "\"title\":\"olingo.odata.test1.BAETAllPrimRT\"," + 
+          "\"target\":\"ESAllPrim(32767)/olingo.odata.test1.BAETAllPrimRT\"" + 
+        "}},";
+
+    Assert.assertTrue(resultString.startsWith(expected));
+  }  
+  
   @Test
   public void entityAllPrimAllNull() throws Exception {
     final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim");
@@ -207,7 +333,14 @@ public class ODataJsonSerializerTest {
   public void entityCollectionStreamed() throws Exception {
     final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim");
     final EntityIterator entityIterator = new EntityIterator() {
-      Iterator<Entity> innerIterator = data.readAll(edmEntitySet).iterator();
+      EntityCollection entityCollection = data.readAll(edmEntitySet);
+      Iterator<Entity> innerIterator = entityCollection.iterator();
+      
+      @Override
+      public List<Operation> getOperations() {
+        return entityCollection.getOperations();
+      } 
+      
       @Override
       public boolean hasNext() {
         return innerIterator.hasNext();
@@ -248,7 +381,14 @@ public class ODataJsonSerializerTest {
   public void entityCollectionStreamedWithError() throws Exception {
     final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim");
     final EntityIterator entityIterator = new EntityIterator() {
-      Iterator<Entity> innerIterator = data.readAll(edmEntitySet).iterator();
+      EntityCollection entityCollection = data.readAll(edmEntitySet);
+      Iterator<Entity> innerIterator = entityCollection.iterator();
+      
+      @Override
+      public List<Operation> getOperations() {
+        return entityCollection.getOperations();
+      } 
+      
       @Override
       public boolean hasNext() {
         return innerIterator.hasNext();
@@ -502,6 +642,114 @@ public class ODataJsonSerializerTest {
   }
 
   @Test
+  public void entityTwoPrimWithMetadataMinimal() throws Exception {
+    final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESTwoPrim");
+    final Entity entity = data.readAll(edmEntitySet).getEntities().get(0);
+    InputStream result = serializer
+          .entity(metadata, edmEntitySet.getEntityType(), entity, EntitySerializerOptions.with()
+                   .contextURL(ContextURL.with().entitySet(edmEntitySet).suffix(Suffix.ENTITY).build())
+                        .build()).getContent();
+    final String resultString = IOUtils.toString(result);
+    final String expectedResult = "{\"@odata.context\":\"$metadata#ESTwoPrim/$entity\"," +
+            "\"@odata.metadataEtag\":\"W/\\\"metadataETag\\\"\"," +
+            "\"PropertyInt16\":32766,\"PropertyString\":\"Test String1\"}";
+        Assert.assertEquals(expectedResult, resultString);
+  }
+
+  @Test
+  public void entitySetTwoPrimWithMetadataFull() throws Exception {
+    final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESTwoPrim");
+    final EntityCollection entitySet = data.readAll(edmEntitySet);
+    InputStream result = serializerFullMetadata
+        .entityCollection(metadata, edmEntitySet.getEntityType(), entitySet,
+            EntityCollectionSerializerOptions.with()
+                .contextURL(ContextURL.with().entitySet(edmEntitySet).build())
+                .build())
+        .getContent();
+    final String resultString = IOUtils.toString(result);
+    final String expectedResult = "{\"@odata.context\":\"$metadata#ESTwoPrim\","
+        + "\"@odata.metadataEtag\":\"W/\\\"metadataETag\\\"\","
+        + "\"value\":[{\"@odata.type\":\"#olingo.odata.test1.ETTwoPrim\",\"@odata.id\":\"ESTwoPrim(32766)\","
+        + "\"PropertyInt16@odata.type\":\"#Int16\",\"PropertyInt16\":32766,"
+        + "\"PropertyString\":\"Test String1\"},"
+        + "{\"@odata.type\":\"#olingo.odata.test1.ETTwoPrim\",\"@odata.id\":\"ESTwoPrim(-365)\","
+        + "\"PropertyInt16@odata.type\":\"#Int16\",\"PropertyInt16\":-365,"
+        + "\"PropertyString\":\"Test String2\","
+        + "\"NavPropertyETAllPrimMany@odata.navigationLink\":\"ESTwoPrim(-365)/NavPropertyETAllPrimMany\"},"
+        + "{\"@odata.type\":\"#olingo.odata.test1.ETTwoPrim\",\"@odata.id\":\"ESTwoPrim(-32766)\","
+        + "\"PropertyInt16@odata.type\":\"#Int16\",\"PropertyInt16\":-32766,"
+        + "\"PropertyString\":null},"
+        + "{\"@odata.type\":\"#olingo.odata.test1.ETTwoPrim\",\"@odata.id\":\"ESTwoPrim(32767)\","
+        + "\"PropertyInt16@odata.type\":\"#Int16\",\"PropertyInt16\":32767,"
+        + "\"PropertyString\":\"Test String4\","
+        + "\"NavPropertyETAllPrimOne@odata.navigationLink\":\"ESAllPrim(32767)\"}]}";
+    Assert.assertEquals(expectedResult, resultString);
+  }
+  
+  @Test
+  public void entityWithStreamMetadataMinimal() throws Exception {
+    final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESWithStream");
+    final EntityCollection collection = data.readAll(edmEntitySet);
+    InputStream result = serializer.entityCollection(metadata, edmEntitySet.getEntityType(), collection,
+        EntityCollectionSerializerOptions.with()
+        .contextURL(ContextURL.with().entitySet(edmEntitySet).build())
+        .build()).getContent();
+    final String resultString = IOUtils.toString(result);
+    final String expectedResult = "{\"@odata.context\":\"$metadata#ESWithStream\","
+        + "\"@odata.metadataEtag\":\"W/\\\"metadataETag\\\"\","
+        + "\"value\":[{\"PropertyInt16\":32767},"
+        + "{\"PropertyInt16\":7,\"PropertyStream@odata.mediaEtag\":\"eTag\","
+        + "\"PropertyStream@odata.mediaContentType\":\"image/jpeg\"}]}";
+    Assert.assertEquals(expectedResult, resultString);
+  }
+  
+  @Test
+  public void entityWithStreamMetadataNone() throws Exception {
+    final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESWithStream");
+    final EntityCollection collection = data.readAll(edmEntitySet);
+    InputStream result = serializerNoMetadata.entityCollection(metadata, edmEntitySet.getEntityType(), collection,
+        EntityCollectionSerializerOptions.with()
+        .contextURL(ContextURL.with().entitySet(edmEntitySet).build())
+        .build()).getContent();
+    final String resultString = IOUtils.toString(result);
+    final String expectedResult = "{"
+        + "\"value\":[{\"PropertyInt16\":32767},"
+        + "{\"PropertyInt16\":7}]}";
+    Assert.assertEquals(expectedResult, resultString);
+  }  
+
+  @Test
+  public void entityWithStreamMetadataFull() throws Exception {
+    final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESWithStream");
+    final EntityCollection collection = data.readAll(edmEntitySet);
+    InputStream result = serializerFullMetadata.entityCollection(metadata, edmEntitySet.getEntityType(), collection,
+        EntityCollectionSerializerOptions.with()
+        .contextURL(ContextURL.with().entitySet(edmEntitySet).build())
+        .build()).getContent();
+    final String resultString = IOUtils.toString(result);
+    final String expectedResult = "{\"@odata.context\":\"$metadata#ESWithStream\","
+        + "\"@odata.metadataEtag\":\"W/\\\"metadataETag\\\"\","
+        + "\"value\":[{"
+        + "\"@odata.type\":\"#olingo.odata.test1.ETWithStream\","
+        + "\"@odata.id\":\"ESWithStream(32767)\","
+        + "\"PropertyInt16@odata.type\":\"#Int16\","
+        + "\"PropertyInt16\":32767,"
+        + "\"PropertyStream@odata.type\":\"#Stream\","
+        + "\"PropertyStream@odata.mediaReadLink\":\"readLink\"},"
+        + "{"
+        + "\"@odata.type\":\"#olingo.odata.test1.ETWithStream\","
+        + "\"@odata.id\":\"ESWithStream(7)\","
+        + "\"PropertyInt16@odata.type\":\"#Int16\","
+        + "\"PropertyInt16\":7,"
+        + "\"PropertyStream@odata.type\":\"#Stream\","
+        + "\"PropertyStream@odata.mediaEtag\":\"eTag\","
+        + "\"PropertyStream@odata.mediaContentType\":\"image/jpeg\","
+        + "\"PropertyStream@odata.mediaEditLink\":\"http://mediaserver:1234/editLink\""
+        + "}]}";
+    Assert.assertEquals(expectedResult, resultString);
+  }  
+  
+  @Test
   public void entitySetTwoPrimNoMetadata() throws Exception {
     final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESTwoPrim");
     final EntityCollection entitySet = data.readAll(edmEntitySet);
@@ -559,6 +807,26 @@ public class ODataJsonSerializerTest {
   }
 
   @Test
+  public void entityMediaWithMetadataFull() throws Exception {
+    final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESMedia");
+    final Entity entity = data.readAll(edmEntitySet).getEntities().get(0);
+    entity.setMediaETag("W/\\\"08D25949E3BFB7AB\\\"");
+    InputStream result = serializerFullMetadata
+        .entity(metadata, edmEntitySet.getEntityType(), entity,
+            EntitySerializerOptions.with().contextURL(ContextURL.with()
+                .entitySet(edmEntitySet).suffix(Suffix.ENTITY).build()).build())
+        .getContent();
+    final String resultString = IOUtils.toString(result);
+    final String expectedResult = "{\"@odata.context\":\"$metadata#ESMedia/$entity\","
+        + "\"@odata.metadataEtag\":\"W/\\\"metadataETag\\\"\","
+        + "\"@odata.mediaEtag\":\"W/\\\\\\\"08D25949E3BFB7AB\\\\\\\"\",\"@odata.mediaContentType\":\"image/svg+xml\","
+        + "\"@odata.mediaEditLink\":\"ESMedia(1)/$value\","
+        + "\"@odata.type\":\"#olingo.odata.test1.ETMedia\",\"@odata.id\":\"ESMedia(1)\","
+        + "\"PropertyInt16@odata.type\":\"#Int16\",\"PropertyInt16\":1}";
+    Assert.assertEquals(expectedResult, resultString);
+  }
+  
+  @Test
   public void primitiveValuesAllNull() throws Exception {
     final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllNullable");
     final EntityCollection entitySet = data.readAll(edmEntitySet);
@@ -932,6 +1200,29 @@ public class ODataJsonSerializerTest {
         .primitive(metadata, (EdmPrimitiveType) edmProperty.getType(), property, null).getContent());
     Assert.assertEquals("{\"value\":\"First Resource - positive values\"}", resultString);
   }
+  
+  @Test
+  public void primitivePropertyWithMetadataFull() throws Exception {
+    final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim");
+    final EdmProperty edmProperty = (EdmProperty) edmEntitySet.getEntityType()
+        .getProperty("PropertyString");
+    final Property property = data.readAll(edmEntitySet).getEntities().get(0)
+        .getProperty(edmProperty.getName());
+    final String resultString = IOUtils
+        .toString(serializerFullMetadata
+            .primitive(metadata, (EdmPrimitiveType) edmProperty.getType(), property,
+                PrimitiveSerializerOptions.with()
+                    .contextURL(ContextURL.with().entitySet(edmEntitySet)
+                        .keyPath("32767")
+                        .navOrPropertyPath(edmProperty.getName()).build())
+                    .build())
+            .getContent());
+    Assert.assertEquals(
+        "{\"@odata.context\":\"$metadata#ESAllPrim(32767)/PropertyString\","
+            + "\"@odata.metadataEtag\":\"W/\\\"metadataETag\\\"\","
+            + "\"value\":\"First Resource - positive values\"}",
+        resultString);
+  } 
 
   @Test(expected = SerializerException.class)
   public void primitivePropertyNull() throws Exception {
@@ -979,6 +1270,25 @@ public class ODataJsonSerializerTest {
   }
 
   @Test
+  public void primitiveCollectionPropertyWithMetadataFull() throws Exception {
+    final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESCollAllPrim");
+    final EdmProperty edmProperty = (EdmProperty) edmEntitySet.getEntityType().getProperty("CollPropertyString");
+    final Property property = data.readAll(edmEntitySet).getEntities().get(0).getProperty(edmProperty.getName());
+
+    final String resultString = IOUtils.toString(serializerFullMetadata
+                .primitiveCollection(metadata, (EdmPrimitiveType) edmProperty.getType(), property,
+                        PrimitiveSerializerOptions.with()
+                                .contextURL(ContextURL.with()
+                                        .entitySet(edmEntitySet).keyPath("1").navOrPropertyPath(edmProperty.getName())
+                                        .build())
+                                .build()).getContent());
+    Assert.assertEquals("{\"@odata.context\":\"$metadata#ESCollAllPrim(1)/CollPropertyString\"," +
+                    "\"@odata.metadataEtag\":\"W/\\\"metadataETag\\\"\"," +
+                    "\"@odata.type\":\"#Collection(String)\",\"value\":[\"Employee1@company.example\"," +
+                    "\"Employee2@company.example\",\"Employee3@company.example\"]}", resultString);
+  }
+
+  @Test
   public void complexProperty() throws Exception {
     final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESMixPrimCollComp");
     final EdmProperty edmProperty = (EdmProperty) edmEntitySet.getEntityType().getProperty("PropertyComp");
@@ -1009,6 +1319,24 @@ public class ODataJsonSerializerTest {
   }
 
   @Test
+  public void complexPropertyWithMetadataFull() throws Exception {
+    final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESMixPrimCollComp");
+    final EdmProperty edmProperty = (EdmProperty) edmEntitySet.getEntityType().getProperty("PropertyComp");
+    final Property property = data.readAll(edmEntitySet).getEntities().get(0).getProperty("PropertyComp");
+    final String resultString = IOUtils.toString(serializerFullMetadata
+             .complex(metadata, (EdmComplexType) edmProperty.getType(), property,
+                    ComplexSerializerOptions.with()
+                            .contextURL(ContextURL.with()
+                                    .entitySet(edmEntitySet).keyPath("32767").navOrPropertyPath(edmProperty.getName())
+                                        .build()).build()).getContent());
+    Assert.assertEquals("{\"@odata.context\":\"$metadata#ESMixPrimCollComp(32767)/PropertyComp\"," +
+                "\"@odata.metadataEtag\":\"W/\\\"metadataETag\\\"\"," +
+                "\"@odata.type\":\"#olingo.odata.test1.CTTwoPrim\"," +
+                "\"PropertyInt16@odata.type\":\"#Int16\",\"PropertyInt16\":111," +
+                "\"PropertyString\":\"TEST A\"}",resultString);
+  }
+
+  @Test
   public void complexCollectionProperty() throws Exception {
     final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESMixPrimCollComp");
     final EdmProperty edmProperty = (EdmProperty) edmEntitySet.getEntityType().getProperty("CollPropertyComp");
@@ -1044,6 +1372,34 @@ public class ODataJsonSerializerTest {
   }
 
   @Test
+  public void complexCollectionPropertyWithMetadataFull() throws Exception {
+    final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESMixPrimCollComp");
+    final EdmProperty edmProperty = (EdmProperty) edmEntitySet.getEntityType().getProperty("CollPropertyComp");
+    final Property property = data.readAll(edmEntitySet).getEntities().get(0).getProperty(edmProperty.getName());
+    final String resultString = IOUtils.toString(serializerFullMetadata
+            .complexCollection(metadata, (EdmComplexType) edmProperty.getType(),
+                property, ComplexSerializerOptions.with()
+                    .contextURL(ContextURL.with().entitySet(edmEntitySet)
+                        .keyPath("32767")
+                        .navOrPropertyPath(edmProperty.getName()).build())
+                    .build())
+            .getContent());
+    final String expectedResult = "{\"@odata.context\":\"$metadata#ESMixPrimCollComp(32767)/CollPropertyComp\","
+        + "\"@odata.metadataEtag\":\"W/\\\"metadataETag\\\"\","
+        + "\"@odata.type\":\"#Collection(olingo.odata.test1.CTTwoPrim)\","
+        + "\"value\":[{\"@odata.type\":\"#olingo.odata.test1.CTTwoPrim\","
+        + "\"PropertyInt16@odata.type\":\"#Int16\",\"PropertyInt16\":123,"
+        + "\"PropertyString\":\"TEST 1\"},"
+        + "{\"@odata.type\":\"#olingo.odata.test1.CTTwoPrim\","
+        + "\"PropertyInt16@odata.type\":\"#Int16\",\"PropertyInt16\":456,"
+        + "\"PropertyString\":\"TEST 2\"},"
+        + "{\"@odata.type\":\"#olingo.odata.test1.CTTwoPrim\","
+        + "\"PropertyInt16@odata.type\":\"#Int16\",\"PropertyInt16\":789,"
+        + "\"PropertyString\":\"TEST 3\"}]}";
+    Assert.assertEquals(expectedResult, resultString);
+  }
+  
+  @Test
   public void entityReference() throws Exception {
     final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim");
     final Entity entity = data.readAll(edmEntitySet).getEntities().get(0);