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/26 14:58:57 UTC

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

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/3c0225c9/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/3c0225c9/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/3c0225c9/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/3c0225c9/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/3c0225c9/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

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/3c0225c9/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/3c0225c9/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/3c0225c9/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/3c0225c9/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/3c0225c9/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/3c0225c9/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/3c0225c9/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/3c0225c9/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/3c0225c9/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/3c0225c9/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/3c0225c9/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")