Repository: olingo-odata4
Updated Branches:
  refs/heads/OLINGO-811 [created] 5dee97f76


OLINGO-811: implementing the =nav/ and =nav/


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

Branch: refs/heads/OLINGO-811
Commit: 5dee97f7628c793e2bbcd3f89d8d5c52e07639ea
Parents: 3786699
Author: Ramesh Reddy <[email protected]>
Authored: Tue Mar 22 18:22:27 2016 -0500
Committer: Ramesh Reddy <[email protected]>
Committed: Tue Mar 22 18:24:43 2016 -0500

----------------------------------------------------------------------
 .../ExpandWithSystemQueryOptionsITCase.java     | 95 ++++++++++++++++++--
 .../olingo/client/api/uri/URIBuilder.java       | 15 ++++
 .../core/serialization/JsonDeserializer.java    | 14 +++
 .../core/serialization/ODataBinderImpl.java     | 59 +++++++++++-
 .../olingo/client/core/uri/URIBuilderImpl.java  | 11 ++-
 .../olingo/client/core/uri/URIBuilderTest.java  | 15 ++++
 .../server/api/uri/queryoption/ExpandItem.java  |  8 +-
 .../serializer/json/ODataJsonSerializer.java    | 65 +++++++++++---
 .../core/serializer/xml/ODataXmlSerializer.java | 47 +++++++---
 .../server/core/uri/parser/ExpandParser.java    |  2 +
 .../core/uri/queryoption/ExpandItemImpl.java    | 10 +++
 .../processor/TechnicalEntityProcessor.java     |  4 +-
 .../ExpandSystemQueryOptionHandler.java         | 41 ++++-----
 13 files changed, 317 insertions(+), 69 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5dee97f7/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/ExpandWithSystemQueryOptionsITCase.java
----------------------------------------------------------------------
diff --git 
a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/ExpandWithSystemQueryOptionsITCase.java
 
b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/ExpandWithSystemQueryOptionsITCase.java
index 0f3743b..5f44351 100644
--- 
a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/ExpandWithSystemQueryOptionsITCase.java
+++ 
b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/ExpandWithSystemQueryOptionsITCase.java
@@ -37,7 +37,6 @@ import org.apache.olingo.client.api.domain.ClientEntity;
 import org.apache.olingo.client.api.domain.ClientEntitySet;
 import org.apache.olingo.client.api.uri.QueryOption;
 import org.apache.olingo.commons.api.http.HttpStatusCode;
-import org.junit.Ignore;
 import org.junit.Test;
 
 public class ExpandWithSystemQueryOptionsITCase extends 
AbstractParamTecSvcITCase {
@@ -209,8 +208,7 @@ public class ExpandWithSystemQueryOptionsITCase extends 
AbstractParamTecSvcITCas
   }
 
   @Test
-  @Ignore("Server do not support navigation property count annotations")
-  public void count() {
+  public void count() throws Exception{
     final ODataClient client = getEdmEnabledClient();
     Map<QueryOption, Object> options = new EnumMap<QueryOption, 
Object>(QueryOption.class);
     options.put(QueryOption.SELECT, "PropertyInt16");
@@ -220,6 +218,7 @@ public class ExpandWithSystemQueryOptionsITCase extends 
AbstractParamTecSvcITCas
         
client.newURIBuilder(SERVICE_URI).appendEntitySetSegment(ES_TWO_KEY_NAV).expandWithOptions(
             NAV_PROPERTY_ET_TWO_KEY_NAV_MANY, 
options).addQueryOption(QueryOption.SELECT,
                 "PropertyInt16,PropertyString").build();
+       
     final ODataRetrieveResponse<ClientEntitySet> response =
         client.getRetrieveRequestFactory().getEntitySetRequest(uri).execute();
 
@@ -232,13 +231,13 @@ public class ExpandWithSystemQueryOptionsITCase extends 
AbstractParamTecSvcITCas
       final ClientEntitySet entitySet =
           
entity.getNavigationLink(NAV_PROPERTY_ET_TWO_KEY_NAV_MANY).asInlineEntitySet().getEntitySet();
 
-      if (propInt16.equals(1) && propString.equals("1")) {
-        assertEquals(Integer.valueOf(2), entitySet.getCount());
-      } else if (propInt16.equals(1) && propString.equals("2")) {
+      if ((propInt16.equals(1) ||propInt16.equals((short)1)) && 
propString.equals("1")) {
         assertEquals(Integer.valueOf(2), entitySet.getCount());
-      } else if (propInt16.equals(2) && propString.equals("1")) {
-        assertEquals(Integer.valueOf(2), entitySet.getCount());
-      } else if (propInt16.equals(3) && propString.equals("1")) {
+      } else if ((propInt16.equals(1) ||propInt16.equals((short)1)) && 
propString.equals("2")) {
+        assertEquals(Integer.valueOf(1), entitySet.getCount());
+      } else if ((propInt16.equals(2) ||propInt16.equals((short)2)) && 
propString.equals("1")) {
+        assertEquals(Integer.valueOf(1), entitySet.getCount());
+      } else if ((propInt16.equals(3) ||propInt16.equals((short)3)) && 
propString.equals("1")) {
         assertEquals(Integer.valueOf(0), entitySet.getCount());
       } else {
         fail();
@@ -247,6 +246,84 @@ public class ExpandWithSystemQueryOptionsITCase extends 
AbstractParamTecSvcITCas
   }
 
   @Test
+  public void countOnly() throws Exception {
+    final ODataClient client = getEdmEnabledClient();
+    Map<QueryOption, Object> options = new EnumMap<QueryOption, 
Object>(QueryOption.class);
+
+    final URI uri =
+        
client.newURIBuilder(SERVICE_URI).appendEntitySetSegment(ES_TWO_KEY_NAV).expandWithOptions(
+            NAV_PROPERTY_ET_TWO_KEY_NAV_MANY, false, true, 
options).addQueryOption(QueryOption.SELECT,
+                "PropertyInt16,PropertyString").build();
+    final ODataRetrieveResponse<ClientEntitySet> response =
+        client.getRetrieveRequestFactory().getEntitySetRequest(uri).execute();
+
+    final List<ClientEntity> entities = response.getBody().getEntities();
+    assertEquals(4, entities.size());
+
+    for (final ClientEntity entity : entities) {
+      final Object propInt16 = 
entity.getProperty(PROPERTY_INT16).getPrimitiveValue().toValue();
+      final Object propString = 
entity.getProperty(PROPERTY_STRING).getPrimitiveValue().toValue();
+      final ClientEntitySet entitySet =
+          
entity.getNavigationLink(NAV_PROPERTY_ET_TWO_KEY_NAV_MANY).asInlineEntitySet().getEntitySet();
+
+      if ((propInt16.equals(1) ||propInt16.equals((short)1)) && 
propString.equals("1")) {
+        assertEquals(Integer.valueOf(2), entitySet.getCount());
+      } else if ((propInt16.equals(1) ||propInt16.equals((short)1)) && 
propString.equals("2")) {
+        assertEquals(Integer.valueOf(1), entitySet.getCount());
+      } else if ((propInt16.equals(2) ||propInt16.equals((short)2)) && 
propString.equals("1")) {
+        assertEquals(Integer.valueOf(1), entitySet.getCount());
+      } else if ((propInt16.equals(3) ||propInt16.equals((short)3)) && 
propString.equals("1")) {
+        assertEquals(Integer.valueOf(0), entitySet.getCount());
+      } else {
+        fail();
+      }
+    }
+  }  
+  
+  @Test
+  public void reference() throws Exception {
+    final ODataClient client = getEdmEnabledClient();
+    Map<QueryOption, Object> options = new EnumMap<QueryOption, 
Object>(QueryOption.class);
+
+    final URI uri =
+        
client.newURIBuilder(SERVICE_URI).appendEntitySetSegment(ES_TWO_KEY_NAV).expandWithOptions(
+            NAV_PROPERTY_ET_TWO_KEY_NAV_MANY, true, false, 
options).addQueryOption(QueryOption.SELECT,
+                "PropertyInt16,PropertyString").build();
+    final ODataRetrieveResponse<ClientEntitySet> response =
+        client.getRetrieveRequestFactory().getEntitySetRequest(uri).execute();
+
+    final List<ClientEntity> entities = response.getBody().getEntities();
+    assertEquals(4, entities.size());
+
+    for (final ClientEntity entity : entities) {
+      final Object propInt16 = 
entity.getProperty(PROPERTY_INT16).getPrimitiveValue().toValue();
+      final Object propString = 
entity.getProperty(PROPERTY_STRING).getPrimitiveValue().toValue();
+      final ClientEntitySet entitySet =
+          
entity.getNavigationLink(NAV_PROPERTY_ET_TWO_KEY_NAV_MANY).asInlineEntitySet().getEntitySet();
+
+      if ((propInt16.equals(1) ||propInt16.equals((short)1)) && 
propString.equals("1")) {
+        assertEquals(2, entitySet.getEntities().size());
+        assertEquals("ESTwoKeyNav(PropertyInt16=1,PropertyString='1')", 
+            entitySet.getEntities().get(0).getId().toString());
+        assertEquals("ESTwoKeyNav(PropertyInt16=1,PropertyString='2')", 
+            entitySet.getEntities().get(1).getId().toString());        
+      } else if ((propInt16.equals(1) ||propInt16.equals((short)1)) && 
propString.equals("2")) {
+        assertEquals(1, entitySet.getEntities().size());
+        assertEquals("ESTwoKeyNav(PropertyInt16=1,PropertyString='1')", 
+            entitySet.getEntities().get(0).getId().toString());
+      } else if ((propInt16.equals(2) ||propInt16.equals((short)2)) && 
propString.equals("1")) {
+        assertEquals(1, entitySet.getEntities().size());
+        assertEquals("ESTwoKeyNav(PropertyInt16=1,PropertyString='2')", 
+            entitySet.getEntities().get(0).getId().toString());
+      } else if ((propInt16.equals(3) ||propInt16.equals((short)3)) && 
propString.equals("1")) {
+        assertEquals(0, entitySet.getEntities().size());
+      } else {
+        fail();
+      }
+    }
+  }  
+  
+  @Test
   public void singleEntityWithExpand() {
     /* A single entity request will be dispatched to a different processor 
method than entity set request */
     final ODataClient client = getEdmEnabledClient();

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5dee97f7/lib/client-api/src/main/java/org/apache/olingo/client/api/uri/URIBuilder.java
----------------------------------------------------------------------
diff --git 
a/lib/client-api/src/main/java/org/apache/olingo/client/api/uri/URIBuilder.java 
b/lib/client-api/src/main/java/org/apache/olingo/client/api/uri/URIBuilder.java
index 7cf0177..b73c68f 100644
--- 
a/lib/client-api/src/main/java/org/apache/olingo/client/api/uri/URIBuilder.java
+++ 
b/lib/client-api/src/main/java/org/apache/olingo/client/api/uri/URIBuilder.java
@@ -351,6 +351,21 @@ public interface URIBuilder {
   URIBuilder expandWithOptions(String expandItem, Map<QueryOption, Object> 
options);
   
   /**
+   * The set of expanded entities can be refined through the application of 
expand options, expressed as a
+   * semicolon-separated list of system query options, enclosed in 
parentheses, see [OData-URL].
+   *
+   * @param expandItem item to be expanded.
+   * @param pathRef include the /$ref at the end of the $expand item's path;if 
true pathCount MUST be false
+   * @param pathCount include /$count at the end of the $expand item's path;if 
true pathRef MUST be false
+   * @param options System query options. Allowed query options are: $filter, 
$select, $orderby, $skip, $top, $count,
+   * $search, $expand, and $levels.
+   * @return current URIBuilder instance.
+   * @see org.apache.olingo.client.api.uri.QueryOption#EXPAND
+   */
+  URIBuilder expandWithOptions(String expandItem, boolean pathRef,
+      boolean pathCount, Map<QueryOption, Object> options);  
+  
+  /**
    * Properties of related entities can be specified by including the $select 
query option within the $expand.
    * <br />
    * <tt>http://host/service/Products?$expand=Category($select=Name)</tt>

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5dee97f7/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/JsonDeserializer.java
----------------------------------------------------------------------
diff --git 
a/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/JsonDeserializer.java
 
b/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/JsonDeserializer.java
index fbfb0f5..3691d8b 100644
--- 
a/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/JsonDeserializer.java
+++ 
b/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/JsonDeserializer.java
@@ -94,6 +94,12 @@ public class JsonDeserializer implements ODataDeserializer {
       final ObjectCodec codec, final Link link) throws IOException {
 
     final String entityNamePrefix = name.substring(0, name.indexOf(suffix));
+
+    Integer count = null;
+    if (tree.hasNonNull(entityNamePrefix+Constants.JSON_COUNT)) {
+      count = tree.get(entityNamePrefix+Constants.JSON_COUNT).asInt();
+    }        
+    
     if (tree.has(entityNamePrefix)) {
       final JsonNode inline = tree.path(entityNamePrefix);
       JsonEntityDeserializer entityDeserializer = new 
JsonEntityDeserializer(serverMode);
@@ -106,6 +112,9 @@ public class JsonDeserializer implements ODataDeserializer {
         link.setType(Constants.ENTITY_SET_NAVIGATION_LINK_TYPE);
 
         final EntityCollection entitySet = new EntityCollection();
+        if (count != null) {
+          entitySet.setCount(count);
+        }
         for (final Iterator<JsonNode> entries = inline.elements(); 
entries.hasNext();) {
           
entitySet.getEntities().add(entityDeserializer.doDeserialize(entries.next().traverse(codec)).getPayload());
         }
@@ -247,6 +256,11 @@ public class JsonDeserializer implements ODataDeserializer 
{
         }
       } else if (type == null && 
field.getKey().endsWith(getJSONAnnotation(Constants.JSON_TYPE))) {
         type = field.getValue().asText();
+      } else if 
(field.getKey().endsWith(getJSONAnnotation(Constants.JSON_COUNT))) {
+        final Property property = new Property();
+        property.setName(field.getKey());
+        property.setValue(ValueType.PRIMITIVE, 
Integer.parseInt(field.getValue().asText()));
+        properties.add(property);
       } else if (annotation == null && customAnnotation.matches() && 
!"odata".equals(customAnnotation.group(2))) {
         annotation = new Annotation();
         annotation.setTerm(customAnnotation.group(2) + "." + 
customAnnotation.group(3));

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5dee97f7/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/ODataBinderImpl.java
----------------------------------------------------------------------
diff --git 
a/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/ODataBinderImpl.java
 
b/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/ODataBinderImpl.java
index f9f29e7..a67de48 100644
--- 
a/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/ODataBinderImpl.java
+++ 
b/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/ODataBinderImpl.java
@@ -23,7 +23,9 @@ import java.net.URI;
 import java.sql.Timestamp;
 import java.util.ArrayList;
 import java.util.Calendar;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 import org.apache.commons.lang3.StringUtils;
 import org.apache.olingo.client.api.EdmEnabledODataClient;
@@ -565,23 +567,50 @@ public class ODataBinderImpl implements ODataBinder {
     return type;
   }
 
-  private ClientLink createLinkFromNavigationProperty(final Property property, 
final String propertyTypeName) {
+  private ClientLink createLinkFromNavigationProperty(final Property property, 
final String propertyTypeName, 
+      final Integer count) {
     if (property.isCollection()) {
       EntityCollection inlineEntitySet = new EntityCollection();
       for (final Object inlined : property.asCollection()) {
         Entity inlineEntity = new Entity();
         inlineEntity.setType(propertyTypeName);
         inlineEntity.getProperties().addAll(((ComplexValue) 
inlined).getValue());
+        copyAnnotations(inlineEntity, (ComplexValue) inlined);
         inlineEntitySet.getEntities().add(inlineEntity);
       }
+      if (count != null) {
+        inlineEntitySet.setCount(count);
+      }
       return createODataInlineEntitySet(inlineEntitySet, null, 
property.getName(), null);
     } else {
       Entity inlineEntity = new Entity();
       inlineEntity.setType(propertyTypeName);
       inlineEntity.getProperties().addAll(property.asComplex().getValue());
+      copyAnnotations(inlineEntity, property.asComplex());
       return createODataInlineEntity(inlineEntity, null, property.getName(), 
null);
     }
   }
+  
+  private void copyAnnotations(Entity inlineEntity, ComplexValue complex) {
+    for (Annotation annotation:complex.getAnnotations()) {
+      if (annotation.getTerm().equals(Constants.JSON_TYPE.substring(1))){
+        inlineEntity.setType((String)annotation.asPrimitive());
+      } else if (annotation.getTerm().equals(Constants.JSON_ID.substring(1))){
+        inlineEntity.setId(URI.create((String)annotation.asPrimitive()));
+      } else if 
(annotation.getTerm().equals(Constants.JSON_ETAG.substring(1))){
+        inlineEntity.setETag((String)annotation.asPrimitive());
+      }
+    }
+  }
+
+  private ClientLink createLinkFromEmptyNavigationProperty(final String 
propertyName, 
+      final Integer count) {
+      EntityCollection inlineEntitySet = new EntityCollection();
+      if (count != null) {
+        inlineEntitySet.setCount(count);
+      }
+      return createODataInlineEntitySet(inlineEntitySet, null, propertyName, 
null);
+  }
 
   @Override
   public ClientEntity getODataEntity(final ResWrap<Entity> resource) {
@@ -650,21 +679,45 @@ public class ODataBinderImpl implements ODataBinder {
       entity.setMediaETag(resource.getPayload().getMediaETag());
     }
 
+    Map<String, Integer> countMap = new HashMap<String, Integer>();
     for (final Property property : resource.getPayload().getProperties()) {
       EdmType propertyType = null;
       if (edmType instanceof EdmEntityType) {
-        final EdmElement edmProperty = ((EdmEntityType) 
edmType).getProperty(property.getName());
+        EdmElement edmProperty = ((EdmEntityType) 
edmType).getProperty(property.getName());
         if (edmProperty != null) {
           propertyType = edmProperty.getType();
           if (edmProperty instanceof EdmNavigationProperty && 
!property.isNull()) {
             final String propertyTypeName = 
propertyType.getFullQualifiedName().getFullQualifiedNameAsString();
-            entity.addLink(createLinkFromNavigationProperty(property, 
propertyTypeName));
+            entity.addLink(createLinkFromNavigationProperty(property, 
propertyTypeName, 
+                countMap.remove(property.getName())));
             continue;
           }
+        } else {
+          int idx =  property.getName().indexOf(Constants.JSON_COUNT);
+          if (idx != -1) {
+            String navigationName = property.getName().substring(0, idx);
+            edmProperty = ((EdmEntityType) 
edmType).getProperty(navigationName);
+            if (edmProperty != null) {
+              if (edmProperty instanceof EdmNavigationProperty) {
+                ClientLink link = entity.getNavigationLink(navigationName);
+                if (link == null) {
+                  countMap.put(navigationName, (Integer)property.getValue());
+                } else {
+                  
link.asInlineEntitySet().getEntitySet().setCount((Integer)property.getValue());
+                }
+              }
+            }            
+          }
         }
       }
       add(entity, getODataProperty(propertyType, property));
     }
+    
+    if (!countMap.isEmpty()) {
+      for (String name:countMap.keySet()) {
+        entity.addLink(createLinkFromEmptyNavigationProperty(name, 
countMap.get(name)));
+      }
+    }
 
     entity.setId(resource.getPayload().getId());
     odataAnnotations(resource.getPayload(), entity);

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5dee97f7/lib/client-core/src/main/java/org/apache/olingo/client/core/uri/URIBuilderImpl.java
----------------------------------------------------------------------
diff --git 
a/lib/client-core/src/main/java/org/apache/olingo/client/core/uri/URIBuilderImpl.java
 
b/lib/client-core/src/main/java/org/apache/olingo/client/core/uri/URIBuilderImpl.java
index b29aca6..dad21ad 100644
--- 
a/lib/client-core/src/main/java/org/apache/olingo/client/core/uri/URIBuilderImpl.java
+++ 
b/lib/client-core/src/main/java/org/apache/olingo/client/core/uri/URIBuilderImpl.java
@@ -446,13 +446,20 @@ public class URIBuilderImpl implements URIBuilder {
 
   @Override
   public URIBuilder expandWithOptions(final String expandItem, final 
Map<QueryOption, Object> options) {
+    return expandWithOptions(expandItem, false, false, options);
+  }
+
+  @Override
+  public URIBuilder expandWithOptions(String expandItem, boolean pathRef,
+      boolean pathCount, Map<QueryOption, Object> options) {
     final Map<String, Object> _options = new LinkedHashMap<String, Object>();
     for (Map.Entry<QueryOption, Object> entry : options.entrySet()) {
       _options.put("$" + entry.getKey().toString(), entry.getValue());
     }
-    return expand(expandItem + buildMultiKeySegment(_options, false, ';'));
+    String path = pathRef?"/$ref":pathCount?"/$count":StringUtils.EMPTY;
+    return expand(expandItem + buildMultiKeySegment(_options, false, 
';')+path);    
   }
-
+  
   @Override
   public URIBuilder expandWithSelect(final String expandItem, final String... 
selectItems) {
     return expand(expandItem + "($select=" + StringUtils.join(selectItems, 
",") + ")");

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5dee97f7/lib/client-core/src/test/java/org/apache/olingo/client/core/uri/URIBuilderTest.java
----------------------------------------------------------------------
diff --git 
a/lib/client-core/src/test/java/org/apache/olingo/client/core/uri/URIBuilderTest.java
 
b/lib/client-core/src/test/java/org/apache/olingo/client/core/uri/URIBuilderTest.java
index 5f9cc8b..ff0be56 100644
--- 
a/lib/client-core/src/test/java/org/apache/olingo/client/core/uri/URIBuilderTest.java
+++ 
b/lib/client-core/src/test/java/org/apache/olingo/client/core/uri/URIBuilderTest.java
@@ -87,6 +87,21 @@ public class URIBuilderTest extends AbstractTest {
     assertEquals(new org.apache.http.client.utils.URIBuilder(SERVICE_ROOT + 
"/Products(5)").
         addParameter("$expand", 
"ProductDetails($expand=ProductInfo;$select=Price),Orders,Customers").build(), 
uri);
   }
+  
+  @Test
+  public void expandWithOptionsCount() throws URISyntaxException {
+    final URI uri = 
client.newURIBuilder(SERVICE_ROOT).appendEntitySetSegment("Products").appendKeySegment(5).
+        expandWithOptions("ProductDetails", false, true, new 
LinkedHashMap<QueryOption, Object>() {
+          private static final long serialVersionUID = 3109256773218160485L;
+          {
+            put(QueryOption.EXPAND, "ProductInfo");
+            put(QueryOption.SELECT, "Price");
+          }
+        }).expand("Orders", "Customers").build();
+    assertEquals(new org.apache.http.client.utils.URIBuilder(SERVICE_ROOT + 
"/Products(5)").
+        addParameter("$expand", 
"ProductDetails($expand=ProductInfo;$select=Price)/$count,Orders,Customers")
+        .build(), uri);
+  }  
 
   public void expandWithLevels() throws URISyntaxException {
     final URI uri = 
client.newURIBuilder(SERVICE_ROOT).appendEntitySetSegment("Products").appendKeySegment(1).

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5dee97f7/lib/server-api/src/main/java/org/apache/olingo/server/api/uri/queryoption/ExpandItem.java
----------------------------------------------------------------------
diff --git 
a/lib/server-api/src/main/java/org/apache/olingo/server/api/uri/queryoption/ExpandItem.java
 
b/lib/server-api/src/main/java/org/apache/olingo/server/api/uri/queryoption/ExpandItem.java
index 6954831..4e71157 100644
--- 
a/lib/server-api/src/main/java/org/apache/olingo/server/api/uri/queryoption/ExpandItem.java
+++ 
b/lib/server-api/src/main/java/org/apache/olingo/server/api/uri/queryoption/ExpandItem.java
@@ -85,11 +85,17 @@ public interface ExpandItem {
 
   /**
    * @return A $ref is used within $expand.
-   * For example: ...?$expand=$ref
+   * For example: ...?$expand=navigation/$ref
    */
   boolean isRef();
 
   /**
+   * @return A $count is used within $expand.
+   * For example: ...?$expand=navigation/$count
+   */  
+  boolean hasCountPath();
+  
+  /**
    * @return Before resource path segments which should be expanded a type 
filter may be used.
    * For example: ...persons?$expand=namespace.managertype/team
    */

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5dee97f7/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 cb60b4e..904bc9a 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
@@ -26,10 +26,10 @@ import java.util.List;
 import java.util.Set;
 
 import org.apache.olingo.commons.api.Constants;
+import org.apache.olingo.commons.api.data.AbstractEntityCollection;
 import org.apache.olingo.commons.api.data.ComplexValue;
 import org.apache.olingo.commons.api.data.ContextURL;
 import org.apache.olingo.commons.api.data.Entity;
-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;
@@ -60,11 +60,12 @@ 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;
 import org.apache.olingo.server.api.uri.queryoption.SelectOption;
-import org.apache.olingo.server.core.serializer.AbstractODataSerializer;
 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;
@@ -402,30 +403,54 @@ public class ODataJsonSerializer extends 
AbstractODataSerializer {
           }
           writeExpandedNavigationProperty(metadata, property, navigationLink,
               innerOptions == null ? null : innerOptions.getExpandOption(),
-                  innerOptions == null ? null : 
innerOptions.getSelectOption(), json);
+              innerOptions == null ? null : innerOptions.getSelectOption(), 
+              innerOptions == null ? null : innerOptions.getCountOption(), 
+              innerOptions == null ? false : innerOptions.hasCountPath(),
+              innerOptions == null ? false : innerOptions.isRef(),             
   
+              json);
         }
       }
     }
   }
-
-  protected void writeExpandedNavigationProperty(final ServiceMetadata 
metadata, final EdmNavigationProperty property,
-      final Link navigationLink, final ExpandOption innerExpand, final 
SelectOption innerSelect,
+  
+  protected void writeExpandedNavigationProperty(
+      final ServiceMetadata metadata, final EdmNavigationProperty property,
+      final Link navigationLink, final ExpandOption innerExpand,
+      final SelectOption innerSelect, final CountOption innerCount,
+      final boolean writeOnlyCount, final boolean writeOnlyRef,
       final JsonGenerator json) throws IOException, SerializerException {
-    json.writeFieldName(property.getName());
+        
     if (property.isCollection()) {
-      if (navigationLink == null || navigationLink.getInlineEntitySet() == 
null) {
-        json.writeStartArray();
-        json.writeEndArray();
-      } else {
-        writeEntitySet(metadata, property.getType(), 
navigationLink.getInlineEntitySet(), innerExpand,
-            innerSelect, false, json);
+      if (writeOnlyCount) {
+        if (navigationLink == null || navigationLink.getInlineEntitySet() == 
null) {
+          writeInlineCount(property.getName(), 0, json);
+        } else {
+          writeInlineCount(property.getName(), 
navigationLink.getInlineEntitySet().getCount(), json);
+        }
+      } else {        
+        if (navigationLink == null || navigationLink.getInlineEntitySet() == 
null) {
+          if (innerCount != null && innerCount.getValue()) {
+            writeInlineCount(property.getName(), 0, json);
+          }          
+          json.writeFieldName(property.getName());
+          json.writeStartArray();
+          json.writeEndArray();
+        } else {
+          if (innerCount != null && innerCount.getValue()) {
+            writeInlineCount(property.getName(), 
navigationLink.getInlineEntitySet().getCount(), json);
+          }
+          json.writeFieldName(property.getName());
+          writeEntitySet(metadata, property.getType(), 
navigationLink.getInlineEntitySet(), innerExpand,
+              innerSelect, writeOnlyRef, json);
+        }
       }
     } else {
+      json.writeFieldName(property.getName());
       if (navigationLink == null || navigationLink.getInlineEntity() == null) {
         json.writeNull();
       } else {
         writeEntity(metadata, property.getType(), 
navigationLink.getInlineEntity(), null,
-            innerExpand, innerSelect, false, json);
+            innerExpand, innerSelect, writeOnlyRef, json);
       }
     }
   }
@@ -852,6 +877,18 @@ public class ODataJsonSerializer extends 
AbstractODataSerializer {
     }
   }
 
+  void writeInlineCount(final String propertyName,
+      final Integer count, final JsonGenerator json)
+      throws IOException {
+    if (count != null) {
+      if (isIEEE754Compatible) {
+        json.writeStringField(propertyName+Constants.JSON_COUNT, 
String.valueOf(count));
+      } else {
+        json.writeNumberField(propertyName+Constants.JSON_COUNT, count);
+      }
+    }
+  }  
+  
   void writeNextLink(final AbstractEntityCollection entitySet, final 
JsonGenerator json) throws IOException {
     if (entitySet.getNext() != null) {
       json.writeStringField(Constants.JSON_NEXT_LINK, 
entitySet.getNext().toASCIIString());

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5dee97f7/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 fa607bd..fecf920 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
@@ -66,6 +66,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.queryoption.CountOption;
 import org.apache.olingo.server.api.uri.queryoption.ExpandItem;
 import org.apache.olingo.server.api.uri.queryoption.ExpandOption;
 import org.apache.olingo.server.api.uri.queryoption.SelectOption;
@@ -254,11 +255,12 @@ public class ODataXmlSerializer extends 
AbstractODataSerializer {
         writeNextLink(entitySet, writer);
       }
 
+      boolean writeOnlyRef = (options != null && 
options.getWriteOnlyReferences());
       if (options == null) {
-        writeEntitySet(metadata, entityType, entitySet, null, null, null, 
writer);
+        writeEntitySet(metadata, entityType, entitySet, null, null, null, 
writer, writeOnlyRef);
       } else {
         writeEntitySet(metadata, entityType, entitySet,
-            options.getExpand(), options.getSelect(), 
options.xml10InvalidCharReplacement(), writer);
+            options.getExpand(), options.getSelect(), 
options.xml10InvalidCharReplacement(), writer, writeOnlyRef);
       }
 
       writer.writeEndElement();
@@ -310,11 +312,12 @@ public class ODataXmlSerializer extends 
AbstractODataSerializer {
         writeCount(entitySet, writer);
       }
 
+      boolean writeOnlyRef = (options != null && 
options.getWriteOnlyReferences());
       if (options == null) {
-        writeEntitySet(metadata, entityType, entitySet, null, null, null, 
writer);
+        writeEntitySet(metadata, entityType, entitySet, null, null, null, 
writer, writeOnlyRef);
       } else {
         writeEntitySet(metadata, entityType, entitySet,
-            options.getExpand(), options.getSelect(), 
options.xml10InvalidCharReplacement(), writer);
+            options.getExpand(), options.getSelect(), 
options.xml10InvalidCharReplacement(), writer, writeOnlyRef);
       }
 
       writer.writeEndElement();
@@ -355,7 +358,7 @@ public class ODataXmlSerializer extends 
AbstractODataSerializer {
           options == null ? null : options.getExpand(),
           options == null ? null : options.getSelect(),
           options == null ? null : options.xml10InvalidCharReplacement(),
-          writer, true);
+          writer, true, false);
       writer.writeEndDocument();
 
       writer.flush();
@@ -395,19 +398,24 @@ public class ODataXmlSerializer extends 
AbstractODataSerializer {
 
   protected void writeEntitySet(final ServiceMetadata metadata, final 
EdmEntityType entityType,
       final AbstractEntityCollection entitySet, final ExpandOption expand, 
final SelectOption select,
-      final String xml10InvalidCharReplacement,final XMLStreamWriter writer) 
+      final String xml10InvalidCharReplacement,final XMLStreamWriter writer, 
final boolean writeOnlyRef) 
           throws XMLStreamException, SerializerException {
     for (final Entity entity : entitySet) {
-      writeEntity(metadata, entityType, entity, null, expand, select, 
xml10InvalidCharReplacement, writer, false);
+      writeEntity(metadata, entityType, entity, null, expand, select, 
+          xml10InvalidCharReplacement, writer, false, writeOnlyRef);
     }
   }
 
   protected void writeEntity(final ServiceMetadata metadata, final 
EdmEntityType entityType,
       final Entity entity, final ContextURL contextURL, final ExpandOption 
expand,
       final SelectOption select, final String xml10InvalidCharReplacement,
-      final XMLStreamWriter writer, final boolean top)
+      final XMLStreamWriter writer, final boolean top, final boolean 
writeOnlyRef)
       throws XMLStreamException, SerializerException {
 
+    if (writeOnlyRef) {
+      writeReference(entity, contextURL, writer, top);
+      return;
+    }
     writer.writeStartElement(ATOM, Constants.ATOM_ELEM_ENTRY, NS_ATOM);
     if (top) {
       writer.writeNamespace(ATOM, NS_ATOM);
@@ -591,7 +599,10 @@ public class ODataXmlSerializer extends 
AbstractODataSerializer {
             writeExpandedNavigationProperty(metadata, property, navigationLink,
                 innerOptions == null ? null : innerOptions.getExpandOption(),
                 innerOptions == null ? null : innerOptions.getSelectOption(),
-                    xml10InvalidCharReplacement, writer);
+                innerOptions == null ? null : innerOptions.getCountOption(),
+                innerOptions == null ? false : innerOptions.hasCountPath(),
+                innerOptions == null ? false : innerOptions.isRef(),           
                         
+                xml10InvalidCharReplacement, writer);
             writer.writeEndElement();
             writer.writeEndElement();
           }
@@ -650,19 +661,27 @@ public class ODataXmlSerializer extends 
AbstractODataSerializer {
 
   protected void writeExpandedNavigationProperty(final ServiceMetadata 
metadata,
       final EdmNavigationProperty property, final Link navigationLink,
-      final ExpandOption innerExpand, final SelectOption innerSelect, final 
String xml10InvalidCharReplacement,
+      final ExpandOption innerExpand, final SelectOption innerSelect, final 
CountOption coutOption, 
+      final boolean writeNavigationCount, final boolean writeOnlyRef,final 
String xml10InvalidCharReplacement,
       final XMLStreamWriter writer) throws XMLStreamException, 
SerializerException {
     if (property.isCollection()) {
       if (navigationLink != null && navigationLink.getInlineEntitySet() != 
null) {
         writer.writeStartElement(ATOM, Constants.ATOM_ELEM_FEED, NS_ATOM);
-        writeEntitySet(metadata, property.getType(), 
navigationLink.getInlineEntitySet(), innerExpand,
-            innerSelect, xml10InvalidCharReplacement, writer);
+        if (writeNavigationCount) {
+          writeCount(navigationLink.getInlineEntitySet(), writer);
+        } else {
+          if (coutOption != null && coutOption.getValue()) {
+            writeCount(navigationLink.getInlineEntitySet(), writer);
+          }
+          writeEntitySet(metadata, property.getType(), 
navigationLink.getInlineEntitySet(), innerExpand,
+              innerSelect, xml10InvalidCharReplacement, writer, writeOnlyRef);
+        }
         writer.writeEndElement();
       }
     } else {
       if (navigationLink != null && navigationLink.getInlineEntity() != null) {
         writeEntity(metadata, property.getType(), 
navigationLink.getInlineEntity(), null,
-            innerExpand, innerSelect, xml10InvalidCharReplacement, writer, 
false);
+            innerExpand, innerSelect, xml10InvalidCharReplacement, writer, 
false, writeOnlyRef);
       }
     }
   }
@@ -1173,7 +1192,7 @@ public class ODataXmlSerializer extends 
AbstractODataSerializer {
   private void writeCount(final AbstractEntityCollection entitySet, final 
XMLStreamWriter writer)
       throws XMLStreamException {
     writer.writeStartElement(METADATA, Constants.ATOM_ELEM_COUNT, NS_METADATA);
-    writer.writeCharacters(String.valueOf(entitySet.getCount()));
+    
writer.writeCharacters(String.valueOf(entitySet.getCount()==null?0:entitySet.getCount()));
     writer.writeEndElement();
   }
 

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5dee97f7/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpandParser.java
----------------------------------------------------------------------
diff --git 
a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpandParser.java
 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpandParser.java
index 2fc0faf..bae2bdd 100644
--- 
a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpandParser.java
+++ 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpandParser.java
@@ -160,10 +160,12 @@ public class ExpandParser {
       if (hasSlash || tokenizer.next(TokenKind.SLASH)) {
         if (tokenizer.next(TokenKind.REF)) {
           resource.addResourcePart(new UriResourceRefImpl());
+          item.setIsRef(true);
           parseOptions(tokenizer, newReferencedType, 
newReferencedIsCollection, item, true, false);
         } else {
           ParserHelper.requireNext(tokenizer, TokenKind.COUNT);
           resource.addResourcePart(new UriResourceCountImpl());
+          item.setCountPath(true);
           parseOptions(tokenizer, newReferencedType, 
newReferencedIsCollection, item, false, true);
         }
       } else {

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5dee97f7/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/ExpandItemImpl.java
----------------------------------------------------------------------
diff --git 
a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/ExpandItemImpl.java
 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/ExpandItemImpl.java
index 3ccea06..c21aa26 100644
--- 
a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/ExpandItemImpl.java
+++ 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/ExpandItemImpl.java
@@ -51,6 +51,7 @@ public class ExpandItemImpl implements ExpandItem {
   private boolean isStar;
 
   private boolean isRef;
+  private boolean hasCountPath;
   private EdmType startTypeFilter;
 
   public ExpandItemImpl setSystemQueryOption(final SystemQueryOption sysItem) {
@@ -187,4 +188,13 @@ public class ExpandItemImpl implements ExpandItem {
     this.startTypeFilter = startTypeFilter;
     return this;
   }
+
+  @Override
+  public boolean hasCountPath() {
+    return this.hasCountPath;
+  }
+  
+  public void setCountPath(boolean value) {
+    this.hasCountPath = value;
+  }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5dee97f7/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 770d90f..c59f3ef 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
@@ -439,7 +439,7 @@ public class TechnicalEntityProcessor extends 
TechnicalProcessor
     final SelectOption select = uriInfo.getSelectOption();
 
     final ExpandSystemQueryOptionHandler expandHandler = new 
ExpandSystemQueryOptionHandler();
-    final Entity entitySerialization = 
expandHandler.transformEntityGraphToTree(entity, edmEntitySet, expand);
+    final Entity entitySerialization = 
expandHandler.transformEntityGraphToTree(entity, edmEntitySet, expand, null);
     expandHandler.applyExpandQueryOptions(entitySerialization, edmEntitySet, 
expand, uriInfo,
         serviceMetadata.getEdm());
 
@@ -515,7 +515,7 @@ public class TechnicalEntityProcessor extends 
TechnicalProcessor
     final ExpandSystemQueryOptionHandler expandHandler = new 
ExpandSystemQueryOptionHandler();
     final EntityCollection entitySetSerialization = 
expandHandler.transformEntitySetGraphToTree(entitySet,
         edmEntitySet,
-        expand);
+        expand, null);
     expandHandler.applyExpandQueryOptions(entitySetSerialization, 
edmEntitySet, expand, uriInfo,
         serviceMetadata.getEdm());
     final CountOption countOption = uriInfo.getCountOption();

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5dee97f7/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 4cc88f8..f3d707a 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
@@ -96,11 +96,8 @@ public class ExpandSystemQueryOptionHandler {
         }
       } else {
         final List<UriResource> uriResourceParts = 
item.getResourcePath().getUriResourceParts();
-        if (uriResourceParts.size() == 1 && uriResourceParts.get(0) instanceof 
UriResourceNavigation) {
+        if (uriResourceParts.get(0) instanceof UriResourceNavigation) {
           navigationProperties.add(((UriResourceNavigation) 
uriResourceParts.get(0)).getProperty());
-        } else {
-          throw new ODataApplicationException("Not supported resource part in 
expand system query option",
-              HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT);
         }
       }
 
@@ -146,19 +143,22 @@ public class ExpandSystemQueryOptionHandler {
   }
 
   public EntityCollection transformEntitySetGraphToTree(final EntityCollection 
entitySet,
-      final EdmBindingTarget edmBindingTarget, final ExpandOption expand) 
throws ODataApplicationException {
+      final EdmBindingTarget edmBindingTarget, final ExpandOption expand, 
+      final ExpandItem expandItem) throws ODataApplicationException {
 
     final EntityCollection newEntitySet = newEntitySet(entitySet);
 
     for (final Entity entity : entitySet.getEntities()) {
-      newEntitySet.getEntities().add(transformEntityGraphToTree(entity, 
edmBindingTarget, expand));
+      newEntitySet.getEntities().add(transformEntityGraphToTree(entity, 
edmBindingTarget, expand, expandItem));
+    }
+    if (expandItem != null && expandItem.hasCountPath()) {
+      newEntitySet.setCount(entitySet.getEntities().size());
     }
-
     return newEntitySet;
   }
 
   public Entity transformEntityGraphToTree(final Entity entity, final 
EdmBindingTarget edmEntitySet,
-      final ExpandOption expand) throws ODataApplicationException {
+      final ExpandOption expand, final ExpandItem parentExpandItem) throws 
ODataApplicationException {
     final Entity newEntity = newEntity(entity);
     if (hasExpandItems(expand)) {
       final boolean expandAll = expandAll(expand);
@@ -173,16 +173,14 @@ public class ExpandSystemQueryOptionHandler {
           final EdmBindingTarget edmBindingTarget = 
edmEntitySet.getRelatedBindingTarget(propertyName);
           final Link newLink = newLink(link);
           newEntity.getNavigationLinks().add(newLink);
-          final ExpandOption innerExpandOption = getInnerExpandOption(expand, 
propertyName);
+          final ExpandItem expandItem = getInnerExpandItem(expand, 
propertyName);
 
           if (edmNavigationProperty.isCollection()) {
             
newLink.setInlineEntitySet(transformEntitySetGraphToTree(link.getInlineEntitySet(),
-                edmBindingTarget,
-                innerExpandOption));
+                edmBindingTarget, expandItem.getExpandOption(), expandItem));
           } else {
             
newLink.setInlineEntity(transformEntityGraphToTree(link.getInlineEntity(),
-                edmBindingTarget,
-                innerExpandOption));
+                edmBindingTarget,expandItem.getExpandOption(), expandItem));
           }
         }
       }
@@ -250,29 +248,24 @@ public class ExpandSystemQueryOptionHandler {
     Set<String> expanded = new HashSet<String>();
     for (final ExpandItem item : expandItems) {
       final List<UriResource> resourceParts = 
item.getResourcePath().getUriResourceParts();
-      if (resourceParts.size() == 1) {
-        final UriResource resource = resourceParts.get(0);
-        if (resource instanceof UriResourceNavigation) {
-          expanded.add(((UriResourceNavigation) 
resource).getProperty().getName());
-        }
-      } else {
-        throw new ODataApplicationException("Expand is not supported within 
complex properties.",
-            HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT);
+      final UriResource resource = resourceParts.get(0);
+      if (resource instanceof UriResourceNavigation) {
+        expanded.add(((UriResourceNavigation) 
resource).getProperty().getName());
       }
     }
     return expanded;
   }
 
-  private ExpandOption getInnerExpandOption(final ExpandOption expand, final 
String propertyName) {
+  private ExpandItem getInnerExpandItem(final ExpandOption expand, final 
String propertyName) {
     for (final ExpandItem item : expand.getExpandItems()) {
       if(item.isStar()) {
-        return item.getExpandOption();
+        return item;
       }
 
       final UriResource resource = 
item.getResourcePath().getUriResourceParts().get(0);
       if (resource instanceof UriResourceNavigation
           && propertyName.equals(((UriResourceNavigation) 
resource).getProperty().getName())) {
-        return item.getExpandOption();
+        return item;
       }
     }
 

Reply via email to