You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by ch...@apache.org on 2017/04/27 11:11:34 UTC

[2/2] olingo-odata4 git commit: [OLINGO-1099] OData V4.0: $levels refactoring

[OLINGO-1099] OData V4.0: $levels refactoring

Signed-off-by: Christian Amend <ch...@sap.com>


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

Branch: refs/heads/master
Commit: f55205561ea5a4f7d37b2015e5f06bfdbb704c89
Parents: 173f0d7
Author: Archana Rai <ar...@sap.com>
Authored: Thu Apr 27 15:47:19 2017 +0530
Committer: Christian Amend <ch...@sap.com>
Committed: Thu Apr 27 13:01:40 2017 +0200

----------------------------------------------------------------------
 .../fit/tecsvc/client/BatchClientITCase.java    |   8 +-
 .../serializer/json/ODataJsonSerializer.java    | 104 +++++++++----------
 .../core/serializer/utils/ContextURLHelper.java |   4 +-
 .../serializer/utils/ExpandSelectHelper.java    |   9 --
 .../core/serializer/xml/ODataXmlSerializer.java | 101 ++++++++----------
 .../ExpandSystemQueryOptionHandler.java         |   2 +-
 .../json/ODataJsonSerializerTest.java           |  17 ++-
 7 files changed, 111 insertions(+), 134 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/f5520556/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BatchClientITCase.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BatchClientITCase.java b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BatchClientITCase.java
index 53bfa58..9e1537d 100644
--- a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BatchClientITCase.java
+++ b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BatchClientITCase.java
@@ -161,7 +161,7 @@ public class BatchClientITCase extends AbstractParamTecSvcITCase {
     assertEquals(1, oDataResponse.getHeader(HttpHeader.ODATA_VERSION).size());
     assertEquals("4.0", oDataResponse.getHeader(HttpHeader.ODATA_VERSION).iterator().next());
     assertEquals(1, oDataResponse.getHeader(HttpHeader.CONTENT_LENGTH).size());
-    assertEquals(isJson() ? "605" : "2246", oDataResponse.getHeader(HttpHeader.CONTENT_LENGTH).iterator().next());
+    assertEquals(isJson() ? "605" : "2223", oDataResponse.getHeader(HttpHeader.CONTENT_LENGTH).iterator().next());
     assertContentType(oDataResponse.getContentType());
   }
 
@@ -193,7 +193,7 @@ public class BatchClientITCase extends AbstractParamTecSvcITCase {
     assertEquals(1, oDataResponse.getHeader(HttpHeader.ODATA_VERSION).size());
     assertEquals("4.0", oDataResponse.getHeader(HttpHeader.ODATA_VERSION).iterator().next());
     assertEquals(1, oDataResponse.getHeader(HttpHeader.CONTENT_LENGTH).size());
-    assertEquals(isJson() ? "605" : "2246", oDataResponse.getHeader(HttpHeader.CONTENT_LENGTH).iterator().next());
+    assertEquals(isJson() ? "605" : "2223", oDataResponse.getHeader(HttpHeader.CONTENT_LENGTH).iterator().next());
     assertContentType(oDataResponse.getContentType());
   }
 
@@ -292,7 +292,7 @@ public class BatchClientITCase extends AbstractParamTecSvcITCase {
     assertEquals(1, oDataResponse.getHeader(HttpHeader.ODATA_VERSION).size());
     assertEquals("4.0", oDataResponse.getHeader(HttpHeader.ODATA_VERSION).iterator().next());
     assertEquals(1, oDataResponse.getHeader(HttpHeader.CONTENT_LENGTH).size());
-    assertEquals(isJson() ? "605" : "2246", oDataResponse.getHeader(HttpHeader.CONTENT_LENGTH).iterator().next());
+    assertEquals(isJson() ? "605" : "2223", oDataResponse.getHeader(HttpHeader.CONTENT_LENGTH).iterator().next());
     assertContentType(oDataResponse.getContentType());
 
     // Check second get request
@@ -398,7 +398,7 @@ public class BatchClientITCase extends AbstractParamTecSvcITCase {
     assertEquals(1, oDataResponse.getHeader(HttpHeader.ODATA_VERSION).size());
     assertEquals("4.0", oDataResponse.getHeader(HttpHeader.ODATA_VERSION).iterator().next());
     assertEquals(1, oDataResponse.getHeader(HttpHeader.CONTENT_LENGTH).size());
-    assertEquals(isJson() ? "605" : "2246", oDataResponse.getHeader(HttpHeader.CONTENT_LENGTH).iterator().next());
+    assertEquals(isJson() ? "605" : "2223", oDataResponse.getHeader(HttpHeader.CONTENT_LENGTH).iterator().next());
     assertContentType(oDataResponse.getContentType());
 
     // Check second get request

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/f5520556/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 c5ac9f3..518b5cc 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
@@ -20,6 +20,7 @@ package org.apache.olingo.server.core.serializer.json;
 
 import java.io.IOException;
 import java.io.OutputStream;
+import java.net.URI;
 import java.util.Collections;
 import java.util.EnumMap;
 import java.util.HashSet;
@@ -180,6 +181,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
       json.writeStartObject();
 
       final ContextURL contextURL = checkContextURL(options == null ? null : options.getContextURL());
+      String name = contextURL == null ? null:contextURL.getEntitySetOrSingletonOrType();
       writeContextURL(contextURL, json);
 
       writeMetadataETag(metadata, json);
@@ -190,10 +192,10 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
       writeOperations(entitySet.getOperations(), json);
       json.writeFieldName(Constants.VALUE);
       if (options == null) {
-        writeEntitySet(metadata, entityType, entitySet, null, null, null, false, null, json);
+        writeEntitySet(metadata, entityType, entitySet, null, null, null, false, null, name, json);
       } else {
         writeEntitySet(metadata, entityType, entitySet,
-            options.getExpand(), null, options.getSelect(), options.getWriteOnlyReferences(), null, json);
+            options.getExpand(), null, options.getSelect(), options.getWriteOnlyReferences(), null, name, json);
       }
       writeNextLink(entitySet, json);
 
@@ -235,11 +237,12 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
         writeInlineCount("", entitySet.getCount(), json);
       }
       json.writeFieldName(Constants.VALUE);
+      String name =  contextURL == null ? null:contextURL.getEntitySetOrSingletonOrType() ;
       if (options == null) {
-        writeEntitySet(metadata, entityType, entitySet, null, null, null, false, null, json);
+        writeEntitySet(metadata, entityType, entitySet, null, null, null, false, null, name, json);
       } else {
         writeEntitySet(metadata, entityType, entitySet,
-            options.getExpand(), null, options.getSelect(), options.getWriteOnlyReferences(), null, json);
+            options.getExpand(), null, options.getSelect(), options.getWriteOnlyReferences(), null, name, json);
       }
       // next link support for streaming results
       writeNextLink(entitySet, json);
@@ -262,12 +265,13 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
       CircleStreamBuffer buffer = new CircleStreamBuffer();
       outputStream = buffer.getOutputStream();
       JsonGenerator json = new JsonFactory().createGenerator(outputStream);
+      String name =  contextURL == null ? null:contextURL.getEntitySetOrSingletonOrType();
       writeEntity(metadata, entityType, entity, contextURL,
           options == null ? null : options.getExpand(),
           null,
           options == null ? null : options.getSelect(),
           options == null ? false : options.getWriteOnlyReferences(),
-          null,
+          null, name,
           json);
 
       json.close();
@@ -293,16 +297,16 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
 
   protected void writeEntitySet(final ServiceMetadata metadata, final EdmEntityType entityType,
       final AbstractEntityCollection entitySet, final ExpandOption expand, Integer toDepth, final SelectOption select,
-      final boolean onlyReference, final Set<String> ancestors, final JsonGenerator json) throws IOException,
-      SerializerException {
+      final boolean onlyReference, final Set<String> ancestors, String name, final JsonGenerator json)
+          throws IOException, SerializerException {
     json.writeStartArray();
     for (final Entity entity : entitySet) {
       if (onlyReference) {
         json.writeStartObject();
-        json.writeStringField(Constants.JSON_ID, getEntityId(entity));
+        json.writeStringField(Constants.JSON_ID, getEntityId(entity, entityType, name));
         json.writeEndObject();
       } else {
-        writeEntity(metadata, entityType, entity, null, expand, toDepth, select, false, ancestors, json);
+        writeEntity(metadata, entityType, entity, null, expand, toDepth, select, false, ancestors, name, json);
       }
     }
     json.writeEndArray();
@@ -313,11 +317,19 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
    * or thrown an {@link SerializerException} if id is <code>null</code>.
    *
    * @param entity the entity
+   * @param entityType 
+   * @param name 
    * @return ascii representation of the entity id
    */
-  private String getEntityId(Entity entity) throws SerializerException {
+  private String getEntityId(Entity entity, EdmEntityType entityType, String name) throws SerializerException {
     if(entity.getId() == null) {
-      throw new SerializerException("Entity id is null.", SerializerException.MessageKeys.MISSING_ID);
+      if(entity == null || entityType == null || entityType.getKeyPredicateNames() == null 
+          || name == null) {
+        throw new SerializerException("Entity id is null.", SerializerException.MessageKeys.MISSING_ID);
+      }else{
+        final UriHelper uriHelper = new UriHelperImpl(); 
+        entity.setId(URI.create(name + '(' + uriHelper.buildKeyPredicate(entityType, entity) + ')'));
+      }
     }
     return entity.getId().toASCIIString();
   }
@@ -337,14 +349,15 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
 
   protected void writeEntity(final ServiceMetadata metadata, final EdmEntityType entityType, final Entity entity,
       final ContextURL contextURL, final ExpandOption expand, Integer toDepth, 
-      final SelectOption select, final boolean onlyReference, Set<String> ancestors, final JsonGenerator json)
+      final SelectOption select, final boolean onlyReference, Set<String> ancestors, 
+      String name, final JsonGenerator json)
       throws IOException, SerializerException {
     boolean cycle = false;
     if (expand != null) {
       if (ancestors == null) {
         ancestors = new HashSet<String>();
       }
-      cycle = !ancestors.add(getEntityId(entity));
+      cycle = !ancestors.add(getEntityId(entity, entityType, name));
     }
     try {
       json.writeStartObject();
@@ -373,14 +386,14 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
         }
       }
       if (cycle || onlyReference) {
-        json.writeStringField(Constants.JSON_ID, getEntityId(entity));
+        json.writeStringField(Constants.JSON_ID, getEntityId(entity, entityType, name));
       } else {
         final EdmEntityType resolvedType = resolveEntityType(metadata, entityType, entity.getType());
         if ((!isODataMetadataNone && !resolvedType.equals(entityType)) || isODataMetadataFull) {
           json.writeStringField(Constants.JSON_TYPE, "#" + entity.getType());
         }
         if ((!isODataMetadataNone && !areKeyPredicateNamesSelected(select, resolvedType)) || isODataMetadataFull) {
-          json.writeStringField(Constants.JSON_ID, getEntityId(entity));
+          json.writeStringField(Constants.JSON_ID, getEntityId(entity, resolvedType, name));
         }
         
         if (isODataMetadataFull) {
@@ -393,13 +406,13 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
         }
         
         writeProperties(metadata, resolvedType, entity.getProperties(), select, json);
-        writeNavigationProperties(metadata, resolvedType, entity, expand, toDepth, ancestors, json);
+        writeNavigationProperties(metadata, resolvedType, entity, expand, toDepth, ancestors, name, json);
         writeOperations(entity.getOperations(), json);      
       }
       json.writeEndObject();
     } finally {
       if (expand != null && !cycle && ancestors != null) {
-        ancestors.remove(getEntityId(entity));
+        ancestors.remove(getEntityId(entity, entityType, name));
       }
     }
   }
@@ -484,7 +497,8 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
 
   protected void writeNavigationProperties(final ServiceMetadata metadata,
       final EdmStructuredType type, final Linked linked, final ExpandOption expand, final Integer toDepth,
-      final Set<String> ancestors, final JsonGenerator json) throws SerializerException, IOException {
+      final Set<String> ancestors, final String name, final JsonGenerator json) 
+          throws SerializerException, IOException {
     if (isODataMetadataFull) {
       for (final String propertyName : type.getNavigationPropertyNames()) {
         final Link navigationLink = linked.getNavigationLink(propertyName);
@@ -501,48 +515,28 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
       final ExpandItem expandAll = ExpandSelectHelper.getExpandAll(expand);
       for (final String propertyName : type.getNavigationPropertyNames()) {
         final ExpandItem innerOptions = ExpandSelectHelper.getExpandItem(expand.getExpandItems(), propertyName);
-        if (toDepth != null) {
-          final EdmNavigationProperty property = type.getNavigationProperty(propertyName);
-          final Link navigationLink = linked.getNavigationLink(property.getName());
-          writeExpandedNavigationProperty(metadata, property, navigationLink,
-                expand, toDepth-1,
-                innerOptions == null ? null : innerOptions.getSelectOption(),
-                innerOptions == null ? null : innerOptions.getCountOption(),
-                innerOptions == null ? false : innerOptions.hasCountPath(),
-                innerOptions == null ? false : innerOptions.isRef(),
-                ancestors,
-                json);
-          continue;
-        }
-        Integer levels = null;
-        if (expandAll != null || innerOptions != null) {
+        if (innerOptions != null || expandAll != null || toDepth != null) {
+          Integer levels = null;
           final EdmNavigationProperty property = type.getNavigationProperty(propertyName);
           final Link navigationLink = linked.getNavigationLink(property.getName());
           ExpandOption childExpand = null;
           LevelsExpandOption levelsOption = null;
           if (innerOptions != null) {
             levelsOption = innerOptions.getLevelsOption();
-            if (levelsOption == null) {
-              childExpand = innerOptions.getExpandOption();
-            } else {
-              ExpandOptionImpl expandOptionImpl = new ExpandOptionImpl();
-              expandOptionImpl.addExpandItem(innerOptions);
-              childExpand = expandOptionImpl;
-            }
+            childExpand = levelsOption == null ? innerOptions.getExpandOption() : new ExpandOptionImpl().addExpandItem(
+                innerOptions);
           } else if (expandAll != null) {
             levels = 1;
             levelsOption = expandAll.getLevelsOption();
-            ExpandOptionImpl expandOptionImpl = new ExpandOptionImpl();
-            expandOptionImpl.addExpandItem(expandAll);
-            childExpand = expandOptionImpl;
+            childExpand = new ExpandOptionImpl().addExpandItem(expandAll);
           }
 
-          if (levelsOption != null) {
-            if (levelsOption.isMax()) {
-              levels = Integer.MAX_VALUE;
-            } else {
-              levels = levelsOption.getValue();
-            }
+          if (levelsOption != null) { 
+            levels = levelsOption.isMax() ? Integer.MAX_VALUE : levelsOption.getValue();
+          }
+          if (toDepth != null) {
+            levels = toDepth - 1;
+            childExpand = expand;
           }
                              
           writeExpandedNavigationProperty(metadata, property, navigationLink,
@@ -551,7 +545,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
             innerOptions == null ? null : innerOptions.getCountOption(),
             innerOptions == null ? false : innerOptions.hasCountPath(),
             innerOptions == null ? false : innerOptions.isRef(),
-            ancestors,
+            ancestors, name,
             json);
         }
       }
@@ -563,7 +557,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
       final Link navigationLink, final ExpandOption innerExpand,
       Integer toDepth, final SelectOption innerSelect, final CountOption innerCount,
       final boolean writeOnlyCount, final boolean writeOnlyRef, final Set<String> ancestors,
-      final JsonGenerator json) throws IOException, SerializerException {
+      String name, final JsonGenerator json) throws IOException, SerializerException {
 
     if (property.isCollection()) {
       if (writeOnlyCount) {
@@ -586,7 +580,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
           }
           json.writeFieldName(property.getName());
           writeEntitySet(metadata, property.getType(), navigationLink.getInlineEntitySet(), innerExpand, toDepth,
-              innerSelect, writeOnlyRef, ancestors, json);
+              innerSelect, writeOnlyRef, ancestors, name, json);
         }
       }
     } else {
@@ -595,7 +589,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
         json.writeNull();
       } else {
         writeEntity(metadata, property.getType(), navigationLink.getInlineEntity(), null,
-            innerExpand, toDepth, innerSelect, writeOnlyRef, ancestors, json);
+            innerExpand, toDepth, innerSelect, writeOnlyRef, ancestors, name, json);
       }
     }
   }
@@ -998,6 +992,8 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
     SerializerException cachedException = null;
     try {
       final ContextURL contextURL = checkContextURL(options == null ? null : options.getContextURL());
+      final String name =  contextURL == null ? null:
+        contextURL.getEntitySetOrSingletonOrType();
       CircleStreamBuffer buffer = new CircleStreamBuffer();
       outputStream = buffer.getOutputStream();
       JsonGenerator json = new JsonFactory().createGenerator(outputStream);
@@ -1014,7 +1010,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
       writeProperties(metadata, type, values, options == null ? null : options.getSelect(), json);
       if (!property.isNull() && property.isComplex()) {
         writeNavigationProperties(metadata, type, property.asComplex(),
-            options == null ? null : options.getExpand(), null, null, json);
+            options == null ? null : options.getExpand(), null, null, name, json);
       }
       json.writeEndObject();
 

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/f5520556/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/utils/ContextURLHelper.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/utils/ContextURLHelper.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/utils/ContextURLHelper.java
index 129f242..66dd84f 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/utils/ContextURLHelper.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/utils/ContextURLHelper.java
@@ -57,7 +57,7 @@ public final class ContextURLHelper {
       handleSelect(type, select, result);
     }
 
-    if (ExpandSelectHelper.hasExpand(expand) && !ExpandSelectHelper.isExpandAll(expand)) {
+    if (ExpandSelectHelper.hasExpand(expand) && !(null != ExpandSelectHelper.getExpandAll(expand))) {
       handleExpand(type, expand, result);
     }
     return result.length() == 0 ? null : result.toString();
@@ -111,7 +111,7 @@ public final class ContextURLHelper {
       if (expandedPropertyNames.contains(propertyName)) {
         final ExpandItem expandItem = ExpandSelectHelper.getExpandItem(expand.getExpandItems(), propertyName);
         if (ExpandSelectHelper.hasExpand(expandItem.getExpandOption())
-            && !ExpandSelectHelper.isExpandAll(expandItem.getExpandOption())
+            && !(null != ExpandSelectHelper.getExpandAll(expandItem.getExpandOption()))
             || ExpandSelectHelper.hasSelect(expandItem.getSelectOption())) {
           final String innerSelectList = buildSelectList(type.getNavigationProperty(propertyName).getType(),
               expandItem.getExpandOption(), expandItem.getSelectOption());

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/f5520556/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/utils/ExpandSelectHelper.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/utils/ExpandSelectHelper.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/utils/ExpandSelectHelper.java
index 4424b61..981b302 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/utils/ExpandSelectHelper.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/utils/ExpandSelectHelper.java
@@ -113,15 +113,6 @@ public abstract class ExpandSelectHelper {
     return expand != null && expand.getExpandItems() != null && !expand.getExpandItems().isEmpty();
   }
 
-  public static boolean isExpandAll(final ExpandOption expand) {
-    for (final ExpandItem item : expand.getExpandItems()) {
-      if (item.isStar()) {
-        return true;
-      }
-    }
-    return false;
-  }
-  
   public static ExpandItem getExpandAll(final ExpandOption expand) {
       for (final ExpandItem item : expand.getExpandItems()) {
         if (item.isStar()) {

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/f5520556/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 c7ea2e2..b66c755 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
@@ -20,6 +20,7 @@ package org.apache.olingo.server.core.serializer.xml;
 
 import java.io.IOException;
 import java.io.OutputStream;
+import java.net.URI;
 import java.text.SimpleDateFormat;
 import java.util.Date;
 import java.util.HashSet;
@@ -67,6 +68,7 @@ import org.apache.olingo.server.api.serializer.ReferenceSerializerOptions;
 import org.apache.olingo.server.api.serializer.SerializerException;
 import org.apache.olingo.server.api.serializer.SerializerResult;
 import org.apache.olingo.server.api.serializer.SerializerStreamResult;
+import org.apache.olingo.server.api.uri.UriHelper;
 import org.apache.olingo.server.api.uri.queryoption.CountOption;
 import org.apache.olingo.server.api.uri.queryoption.ExpandItem;
 import org.apache.olingo.server.api.uri.queryoption.ExpandOption;
@@ -78,6 +80,7 @@ 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.ContextURLBuilder;
 import org.apache.olingo.server.core.serializer.utils.ExpandSelectHelper;
+import org.apache.olingo.server.core.uri.UriHelperImpl;
 import org.apache.olingo.server.core.uri.queryoption.ExpandOptionImpl;
 
 public class ODataXmlSerializer extends AbstractODataSerializer {
@@ -221,6 +224,7 @@ public class ODataXmlSerializer extends AbstractODataSerializer {
       final EntityCollectionSerializerOptions options) throws SerializerException {
 
     final ContextURL contextURL = checkContextURL(options == null ? null : options.getContextURL());
+    final String name = contextURL == null ? null : contextURL.getEntitySetOrSingletonOrType();
     if (options != null && options.getWriteOnlyReferences()) {
       ReferenceCollectionSerializerOptions rso = ReferenceCollectionSerializerOptions.with()
           .contextURL(contextURL).build();
@@ -259,11 +263,11 @@ public class ODataXmlSerializer extends AbstractODataSerializer {
 
       boolean writeOnlyRef = (options != null && options.getWriteOnlyReferences());
       if (options == null) {
-        writeEntitySet(metadata, entityType, entitySet, null, null, null, null, writer, writeOnlyRef, null);
+        writeEntitySet(metadata, entityType, entitySet, null, null, null, null, writer, writeOnlyRef, name, null);
       } else {
         writeEntitySet(metadata, entityType, entitySet,
             options.getExpand(), null, 
-            options.getSelect(), options.xml10InvalidCharReplacement(), writer, writeOnlyRef, null);
+            options.getSelect(), options.xml10InvalidCharReplacement(), writer, writeOnlyRef, name, null);
       }
 
       writer.writeEndElement();
@@ -291,6 +295,7 @@ public class ODataXmlSerializer extends AbstractODataSerializer {
       EntityCollectionSerializerOptions options, OutputStream outputStream) throws SerializerException {
 
     final ContextURL contextURL = checkContextURL(options == null ? null : options.getContextURL());
+    final String name = contextURL == null ? null : contextURL.getEntitySetOrSingletonOrType();
     SerializerException cachedException;
     try {
       XMLStreamWriter writer = XMLOutputFactory.newInstance().createXMLStreamWriter(outputStream, DEFAULT_CHARSET);
@@ -319,11 +324,11 @@ public class ODataXmlSerializer extends AbstractODataSerializer {
       }
       boolean writeOnlyRef = (options != null && options.getWriteOnlyReferences());
       if (options == null) {
-        writeEntitySet(metadata, entityType, entitySet, null, null, null, null, writer, writeOnlyRef,null);
+        writeEntitySet(metadata, entityType, entitySet, null, null, null, null, writer, writeOnlyRef, name, null);
       } else {
         writeEntitySet(metadata, entityType, entitySet,
             options.getExpand(), null, 
-            options.getSelect(), options.xml10InvalidCharReplacement(), writer, writeOnlyRef,null);
+            options.getSelect(), options.xml10InvalidCharReplacement(), writer, writeOnlyRef, name, null);
       }
 
       writer.writeEndElement();
@@ -347,7 +352,7 @@ public class ODataXmlSerializer extends AbstractODataSerializer {
   public SerializerResult entity(final ServiceMetadata metadata, final EdmEntityType entityType,
       final Entity entity, final EntitySerializerOptions options) throws SerializerException {
     final ContextURL contextURL = checkContextURL(options == null ? null : options.getContextURL());
-
+    final String name = contextURL == null ? null : contextURL.getEntitySetOrSingletonOrType();
     if (options != null && options.getWriteOnlyReferences()) {
       return entityReference(entity,
           ReferenceSerializerOptions.with().contextURL(contextURL).build());
@@ -365,7 +370,7 @@ public class ODataXmlSerializer extends AbstractODataSerializer {
           null,
           options == null ? null : options.getSelect(),
           options == null ? null : options.xml10InvalidCharReplacement(),
-          writer, true, false, null);
+          writer, true, false, name, null);
       writer.writeEndDocument();
 
       writer.flush();
@@ -407,11 +412,11 @@ public class ODataXmlSerializer extends AbstractODataSerializer {
       final AbstractEntityCollection entitySet, final ExpandOption expand, 
       final Integer toDepth, final SelectOption select,
       final String xml10InvalidCharReplacement,final XMLStreamWriter writer, 
-      final boolean writeOnlyRef,final Set<String> ancestors) 
+      final boolean writeOnlyRef, final String name,final Set<String> ancestors) 
           throws XMLStreamException, SerializerException {
     for (final Entity entity : entitySet) {
       writeEntity(metadata, entityType, entity, null, expand, toDepth, select, 
-          xml10InvalidCharReplacement, writer, false, writeOnlyRef, ancestors);
+          xml10InvalidCharReplacement, writer, false, writeOnlyRef, name, ancestors);
     }
   }
   
@@ -420,26 +425,35 @@ public class ODataXmlSerializer extends AbstractODataSerializer {
    * or thrown an {@link SerializerException} if id is <code>null</code>.
    *
    * @param entity the entity
+   * @param entityType the entity Type
+   * @param name the entity name
    * @return ascii representation of the entity id
    */
-  private String getEntityId(Entity entity) throws SerializerException {
+  private String getEntityId(Entity entity, EdmEntityType entityType, String name) throws SerializerException {
     if(entity.getId() == null) {
-      throw new SerializerException("Entity id is null.", SerializerException.MessageKeys.MISSING_ID);
+      if((entity == null || entityType == null || entityType.getKeyPredicateNames() == null 
+          || name == null)) {
+        throw new SerializerException("Entity id is null.", SerializerException.MessageKeys.MISSING_ID);
+      }else{
+        final UriHelper uriHelper = new UriHelperImpl(); 
+        entity.setId(URI.create(name + '(' + uriHelper.buildKeyPredicate(entityType, entity) + ')'));
+      }
     }
     return entity.getId().toASCIIString();
   }  
 
+
   protected void writeEntity(final ServiceMetadata metadata, final EdmEntityType entityType,
       final Entity entity, final ContextURL contextURL, final ExpandOption expand, final Integer toDepth,
       final SelectOption select, final String xml10InvalidCharReplacement,
-      final XMLStreamWriter writer, final boolean top, final boolean writeOnlyRef, Set<String> ancestors)
+      final XMLStreamWriter writer, final boolean top, final boolean writeOnlyRef,String name,  Set<String> ancestors)
       throws XMLStreamException, SerializerException {
     boolean cycle = false;
     if (expand != null) {
       if (ancestors == null) {
         ancestors = new HashSet<String>();
       }
-      cycle = !ancestors.add(getEntityId(entity));
+      cycle = !ancestors.add(getEntityId(entity, entityType, name));
     }
 
     if (cycle || writeOnlyRef) {
@@ -498,7 +512,7 @@ public class ODataXmlSerializer extends AbstractODataSerializer {
   
       EdmEntityType resolvedType = resolveEntityType(metadata, entityType, entity.getType());
       writeNavigationProperties(metadata, resolvedType, entity, expand,
-        toDepth, xml10InvalidCharReplacement, ancestors, writer);
+        toDepth, xml10InvalidCharReplacement, ancestors, name, writer);
   
       writer.writeStartElement(ATOM, Constants.ATOM_ELEM_CATEGORY, NS_ATOM);
       writer.writeAttribute(Constants.ATOM_ATTR_SCHEME, Constants.NS_SCHEME);
@@ -525,7 +539,7 @@ public class ODataXmlSerializer extends AbstractODataSerializer {
       writer.writeEndElement(); // entry
     } finally {
       if (!cycle && ancestors != null) {
-        ancestors.remove(getEntityId(entity));
+        ancestors.remove(getEntityId(entity, entityType, name));
       }
     }
   }
@@ -629,59 +643,36 @@ public class ODataXmlSerializer extends AbstractODataSerializer {
 
   protected void writeNavigationProperties(final ServiceMetadata metadata,
       final EdmStructuredType type, final Linked linked, final ExpandOption expand, final Integer toDepth,
-      final String xml10InvalidCharReplacement, final Set<String> ancestors, final XMLStreamWriter writer) 
+      final String xml10InvalidCharReplacement, final Set<String> ancestors, String name, final XMLStreamWriter writer) 
           throws SerializerException, XMLStreamException {
     if ((toDepth != null && toDepth > 1) || (toDepth == null && ExpandSelectHelper.hasExpand(expand))) {
       final ExpandItem expandAll = ExpandSelectHelper.getExpandAll(expand);
       for (final String propertyName : type.getNavigationPropertyNames()) {
         final ExpandItem innerOptions = ExpandSelectHelper.getExpandItem(expand.getExpandItems(), propertyName);
-        if (toDepth != null) {
-          final EdmNavigationProperty property = type.getNavigationProperty(propertyName);
-          final Link navigationLink = getOrCreateLink(linked, propertyName);
-          writeLink(writer, navigationLink, false);
-          writer.writeStartElement(METADATA, Constants.ATOM_ELEM_INLINE, NS_METADATA);
-          writeExpandedNavigationProperty(metadata, property, navigationLink,
-              expand, toDepth - 1,
-              innerOptions == null ? null : innerOptions.getSelectOption(),
-              innerOptions == null ? null : innerOptions.getCountOption(),
-              innerOptions == null ? false : innerOptions.hasCountPath(),
-              innerOptions == null ? false : innerOptions.isRef(),                                    
-              xml10InvalidCharReplacement, ancestors, writer);
-          writer.writeEndElement();
-          writer.writeEndElement();
-          continue;
-        }
-        Integer levels = null;
-        if (expandAll != null || innerOptions != null) {
+        if (expandAll != null || innerOptions != null || toDepth != null) {
+          Integer levels = null;
           final EdmNavigationProperty property = type.getNavigationProperty(propertyName);
           final Link navigationLink = getOrCreateLink(linked, propertyName);
           ExpandOption childExpand = null;
           LevelsExpandOption levelsOption = null;
           if (innerOptions != null) {
             levelsOption = innerOptions.getLevelsOption();
-            if (levelsOption == null) {
-              childExpand = innerOptions.getExpandOption();
-            } else {
-              ExpandOptionImpl expandOptionImpl = new ExpandOptionImpl();
-              expandOptionImpl.addExpandItem(innerOptions);
-              childExpand = expandOptionImpl;
-            }
+            childExpand = levelsOption == null ? innerOptions.getExpandOption() :
+              new ExpandOptionImpl().addExpandItem(innerOptions);
           } else if (expandAll != null) {
             levels = 1;
             levelsOption = expandAll.getLevelsOption();
-            ExpandOptionImpl expandOptionImpl = new ExpandOptionImpl();
-            expandOptionImpl.addExpandItem(expandAll);
-            childExpand = expandOptionImpl;
-          }  
-
+            childExpand = new ExpandOptionImpl().addExpandItem(expandAll);
+          } 
+          
           if (levelsOption != null) {
-            if (levelsOption.isMax()) {
-              levels = Integer.MAX_VALUE;
-            } else {
-              levels = levelsOption.getValue();
-            }
+            levels = levelsOption.isMax() ? Integer.MAX_VALUE :
+              levelsOption.getValue();
+          }
+          if (toDepth != null) {
+            levels = toDepth - 1;
+            childExpand = expand;
           }
-          
           writeLink(writer, navigationLink, false);
           writer.writeStartElement(METADATA, Constants.ATOM_ELEM_INLINE, NS_METADATA);
           writeExpandedNavigationProperty(metadata, property, navigationLink,
@@ -690,7 +681,7 @@ public class ODataXmlSerializer extends AbstractODataSerializer {
             innerOptions == null ? null : innerOptions.getCountOption(),
             innerOptions == null ? false : innerOptions.hasCountPath(),
             innerOptions == null ? false : innerOptions.isRef(),                                    
-            xml10InvalidCharReplacement, ancestors, writer);
+            xml10InvalidCharReplacement, ancestors, name, writer);
           writer.writeEndElement();
           writer.writeEndElement();
         } else {
@@ -751,7 +742,7 @@ public class ODataXmlSerializer extends AbstractODataSerializer {
       final ExpandOption innerExpand, final Integer toDepth, 
       final SelectOption innerSelect, final CountOption coutOption, 
       final boolean writeNavigationCount, final boolean writeOnlyRef,final String xml10InvalidCharReplacement,
-      final Set<String> ancestors,
+      final Set<String> ancestors, String name,
       final XMLStreamWriter writer) throws XMLStreamException, SerializerException {
     if (property.isCollection()) {
       if (navigationLink != null && navigationLink.getInlineEntitySet() != null) {
@@ -763,7 +754,7 @@ public class ODataXmlSerializer extends AbstractODataSerializer {
             writeCount(navigationLink.getInlineEntitySet(), writer);
           }
           writeEntitySet(metadata, property.getType(), navigationLink.getInlineEntitySet(), innerExpand, toDepth,
-              innerSelect, xml10InvalidCharReplacement, writer, writeOnlyRef, ancestors);
+              innerSelect, xml10InvalidCharReplacement, writer, writeOnlyRef, name, ancestors);
         }
         writer.writeEndElement();
       }
@@ -771,7 +762,7 @@ public class ODataXmlSerializer extends AbstractODataSerializer {
       if (navigationLink != null && navigationLink.getInlineEntity() != null) {
         writeEntity(metadata, property.getType(), navigationLink.getInlineEntity(), null,
             innerExpand, toDepth, innerSelect, xml10InvalidCharReplacement, writer, 
-            false, writeOnlyRef, ancestors);
+            false, writeOnlyRef, name, ancestors);
       }
     }
   }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/f5520556/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 7ddad53..8886a0c 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
@@ -217,7 +217,7 @@ public class ExpandSystemQueryOptionHandler {
     newEntity.getAssociationLinks().addAll(entity.getAssociationLinks());
     newEntity.getNavigationBindings().addAll(entity.getNavigationBindings());
     newEntity.getOperations().addAll(entity.getOperations());
-
+    newEntity.getNavigationLinks().addAll(entity.getNavigationLinks());
     return newEntity;
   }
 

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/f5520556/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 9796aef..4ce1768 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
@@ -1286,7 +1286,7 @@ public class ODataJsonSerializerTest {
     Assert.assertEquals(false, resultString.contains(METADATA_TEXT));
   }
 
-  @Test(expected = SerializerException.class)
+  @Test
   public void selectMissingId() throws Exception {
     final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim");
     final EdmEntityType entityType = edmEntitySet.getEntityType();
@@ -1296,20 +1296,19 @@ public class ODataJsonSerializerTest {
     final SelectItem selectItem2 = ExpandSelectMock.mockSelectItem(edmEntitySet, "PropertyBoolean");
     final SelectOption select = ExpandSelectMock.mockSelectOption(Arrays.asList(
         selectItem1, selectItem2, selectItem2));
-
-    try {
-    serializer.entity(metadata, entityType, entity,
+      InputStream result = serializer.entity(metadata, entityType, entity,
             EntitySerializerOptions.with()
                 .contextURL(ContextURL.with().entitySet(edmEntitySet)
                     .selectList(helper.buildContextURLSelectList(entityType, null, select))
                     .suffix(Suffix.ENTITY).build())
                 .select(select)
                 .build()).getContent();
-      Assert.fail("Expected exception not thrown!");
-    } catch (final SerializerException e) {
-      Assert.assertEquals(SerializerException.MessageKeys.MISSING_ID, e.getMessageKey());
-      throw e;
-    }
+          Assert.assertNotNull(result);   
+          final String resultString = IOUtils.toString(result);
+           Assert.assertEquals(  "{\"@odata.context\":\"$metadata#ESAllPrim(PropertyBoolean,PropertyDate)/$entity\","+
+           "\"@odata.metadataEtag\":\"W/\\\"metadataETag\\\"\",\"@odata.id\":\"ESAllPrim(32767)\","+
+            "\"PropertyBoolean\":true,\"PropertyDate\":\"2012-12-03\"}",
+          resultString);   
   }
 
   @Test