[OLINGO-446] support for $ref serialization

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

Branch: refs/heads/OLINGO-632_OSGi-Support
Commit: a2a07242ec7fb726367e72a73e874ae5348b9a25
Parents: bec8cb3
Author: Christian Holzer <[email protected]>
Authored: Fri May 8 17:46:40 2015 +0200
Committer: Christian Holzer <[email protected]>
Committed: Tue May 19 14:33:19 2015 +0200

----------------------------------------------------------------------
 .../tecsvc/client/EntityReferencesITCase.java   | 215 +++++++++++++++
 .../fit/tecsvc/http/EntityReferenceITCase.java  |  91 +++++++
 .../server/api/serializer/ODataSerializer.java  |  28 ++
 .../serializer/json/ODataJsonSerializer.java    |  90 ++++++-
 .../serializer/xml/ODataXmlSerializerImpl.java  |  16 ++
 .../processor/TechnicalEntityProcessor.java     | 261 +++++++++++++------
 .../json/ODataJsonSerializerTest.java           |  47 ++++
 .../core/uri/antlr/TestFullResourcePath.java    |   5 +-
 8 files changed, 666 insertions(+), 87 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a2a07242/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/EntityReferencesITCase.java
----------------------------------------------------------------------
diff --git 
a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/EntityReferencesITCase.java
 
b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/EntityReferencesITCase.java
new file mode 100644
index 0000000..e07b804
--- /dev/null
+++ 
b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/EntityReferencesITCase.java
@@ -0,0 +1,215 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.olingo.fit.tecsvc.client;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
+
+import java.net.URI;
+import java.util.List;
+
+import org.apache.olingo.client.api.EdmEnabledODataClient;
+import org.apache.olingo.client.api.ODataClient;
+import org.apache.olingo.client.api.communication.ODataClientErrorException;
+import 
org.apache.olingo.client.api.communication.response.ODataRetrieveResponse;
+import org.apache.olingo.client.api.domain.ClientEntity;
+import org.apache.olingo.client.api.domain.ClientEntitySet;
+import org.apache.olingo.client.core.ODataClientFactory;
+import org.apache.olingo.commons.api.format.ODataFormat;
+import org.apache.olingo.commons.api.http.HttpStatusCode;
+import org.apache.olingo.fit.AbstractBaseTestITCase;
+import org.apache.olingo.fit.tecsvc.TecSvcConst;
+import org.junit.Test;
+
+public class EntityReferencesITCase extends AbstractBaseTestITCase {
+  
+  private static final String SERVICE_URI = TecSvcConst.BASE_URI;
+  private static final String ES_ALL_PRIM = "ESAllPrim";
+  private static final String PROPERTY_INT_16 = "PropertyInt16";
+  private static final String ES_SERVER_SIDE_PAGING = "ESServerSidePaging";
+  private static final String NAV_PROPERTY_ET_TWO_PRIM_ONE = 
"NavPropertyETTwoPrimOne";
+  private static final String NAV_PROPERTY_ET_TWO_PRIM_MANY = 
"NavPropertyETTwoPrimMany";
+  private static final String DESCENDING = " desc";
+  
+  @Test
+  public void testOrderBy() {
+    final ODataClient client = getClient();
+    final URI uri = client.newURIBuilder(SERVICE_URI)
+                          .appendEntitySetSegment(ES_ALL_PRIM)
+                          .appendRefSegment()
+                          .orderBy(PROPERTY_INT_16).build();
+    
+    executeCollection(uri, 3, "ESAllPrim(-32768)", "ESAllPrim(0)", 
"ESAllPrim(32767)");
+  }
+  
+  @Test
+  public void testOrderByReverse() {
+    final ODataClient client = getClient();
+    final URI uri = client.newURIBuilder(SERVICE_URI)
+                          .appendEntitySetSegment(ES_ALL_PRIM)
+                          .appendRefSegment()
+                          .orderBy(PROPERTY_INT_16 + DESCENDING).build();
+    
+    executeCollection(uri, 3, "ESAllPrim(32767)", "ESAllPrim(0)", 
"ESAllPrim(-32768)");
+  }
+  
+  @Test
+  public void testNavigationToOne() {
+    final ODataClient client = getClient();
+    final URI uri = client.newURIBuilder(SERVICE_URI)
+                          
.appendEntitySetSegment(ES_ALL_PRIM).appendKeySegment(32767)
+                          
.appendNavigationSegment(NAV_PROPERTY_ET_TWO_PRIM_ONE).appendRefSegment().build();
+    
+    final ODataRetrieveResponse<ClientEntity> response = 
client.getRetrieveRequestFactory()
+                                                                
.getEntityRequest(uri)
+                                                                .execute();
+    
+    assertEquals("ESTwoPrim(32767)", 
response.getBody().getId().toASCIIString());
+  }
+  
+  @Test
+  public void testNavigationToMany() {
+    final ODataClient client = getClient();
+    final URI uri = client.newURIBuilder(SERVICE_URI)
+                          
.appendEntitySetSegment(ES_ALL_PRIM).appendKeySegment(0)
+                          
.appendNavigationSegment(NAV_PROPERTY_ET_TWO_PRIM_MANY).orderBy(PROPERTY_INT_16)
+                          .appendRefSegment().build();
+    
+    executeCollection(uri, 3, "ESTwoPrim(-32766)", "ESTwoPrim(32766)", 
"ESTwoPrim(32767)");
+  }
+  
+  @Test
+  public void testFilter() {
+    final ODataClient client = getClient();
+    final URI uri = client.newURIBuilder(SERVICE_URI)
+                          
.appendEntitySetSegment(ES_ALL_PRIM).appendRefSegment()
+                          .filter("PropertyDecimal eq 34").build();
+
+    executeCollection(uri, 1, "ESAllPrim(32767)");
+  }
+  
+  @Test
+  public void testCount() {
+    final ODataClient client = getClient();
+    final URI uri = client.newURIBuilder(SERVICE_URI)
+                          
.appendEntitySetSegment(ES_ALL_PRIM).appendRefSegment().count(true).build();
+    
+    final ODataRetrieveResponse<ClientEntitySet> response = 
client.getRetrieveRequestFactory()
+        .getEntitySetRequest(uri)
+        .execute();
+    
+    assertEquals(Integer.valueOf(3), response.getBody().getCount());
+  }
+  
+  @Test
+  public void testSkip() {
+    final ODataClient client = getClient();
+    final URI uri = client.newURIBuilder(SERVICE_URI)
+                          .appendEntitySetSegment(ES_ALL_PRIM)
+                          .appendRefSegment()
+                          .orderBy(PROPERTY_INT_16).skip(2).build();
+    
+    executeCollection(uri, 1, "ESAllPrim(32767)");
+  }
+  
+  @Test
+  public void testServerDrivenPaging() {
+    final ODataClient client = getClient();
+    URI uri = client.newURIBuilder(SERVICE_URI)
+                          .appendEntitySetSegment(ES_SERVER_SIDE_PAGING)
+                          .appendRefSegment().build();
+    
+    int entityId = 1;
+    final int EXPECTED_REQUESTS = 51;
+    for(int requestCount = 0; requestCount < EXPECTED_REQUESTS; 
requestCount++) {
+      ODataRetrieveResponse<ClientEntitySet> response = 
client.getRetrieveRequestFactory()
+                                                                    
.getEntitySetRequest(uri)
+                                                                    .execute();
+      
+      List<ClientEntity> entities = response.getBody().getEntities();
+      assertEquals(Math.min(10, 503 - (entityId - 1)), entities.size());
+      
+      for( int i = 0; i < entities.size(); i++) {
+        final String entityID = entities.get(i).getId().toASCIIString();
+        assertEquals(ES_SERVER_SIDE_PAGING + "(" + (entityId++) + ")", 
entityID);
+      }
+      
+      if(requestCount < (EXPECTED_REQUESTS - 1)) {
+        assertNotNull(response.getBody().getNext());
+      } else {
+        assertNull(response.getBody().getNext());
+      }
+      uri = response.getBody().getNext();
+    }
+  }
+  
+  @Test
+  public void testResponseNonExistingEntity() {
+    final ODataClient client = getClient();
+    final URI uri = client.newURIBuilder(SERVICE_URI)
+                          
.appendEntitySetSegment(ES_ALL_PRIM).appendKeySegment(0)
+                          
.appendNavigationSegment(NAV_PROPERTY_ET_TWO_PRIM_ONE).appendRefSegment().build();
+    
+    try {
+      client.getRetrieveRequestFactory()
+            .getEntityRequest(uri)
+            .execute();
+      fail();
+    } catch(ODataClientErrorException e) {
+      assertEquals(HttpStatusCode.NOT_FOUND.getStatusCode(), 
e.getStatusLine().getStatusCode());
+    }
+  }
+    
+  @Test
+  public void testEmptyCollection() {
+    final ODataClient client = getClient();
+    final URI uri = client.newURIBuilder(SERVICE_URI)
+                          .appendEntitySetSegment(ES_ALL_PRIM)
+                          .appendKeySegment(-32768)
+                          
.appendNavigationSegment(NAV_PROPERTY_ET_TWO_PRIM_MANY)
+                          .appendRefSegment().build();
+    
+    executeCollection(uri, 0, new String[0]);
+  }
+  
+  private void executeCollection(final URI uri, final int count, final 
String... expected) {
+    final ODataClient client = getClient();
+    final ODataRetrieveResponse<ClientEntitySet> response = 
client.getRetrieveRequestFactory()
+                                                                  
.getEntitySetRequest(uri)
+                                                                  .execute();
+    
+    final List<ClientEntity> entities = response.getBody().getEntities();
+    assertEquals(count, entities.size());
+    
+    for( int i = 0; i < entities.size(); i++) {
+      final String entityID = entities.get(i).getId().toASCIIString();
+      assertEquals(expected[i], entityID);
+    }
+  }
+  
+  @Override
+  protected ODataClient getClient() {
+    final EdmEnabledODataClient client = 
ODataClientFactory.getEdmEnabledClient(SERVICE_URI);
+    client.getConfiguration().setDefaultPubFormat(ODataFormat.JSON);
+    
+    return client;
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a2a07242/fit/src/test/java/org/apache/olingo/fit/tecsvc/http/EntityReferenceITCase.java
----------------------------------------------------------------------
diff --git 
a/fit/src/test/java/org/apache/olingo/fit/tecsvc/http/EntityReferenceITCase.java
 
b/fit/src/test/java/org/apache/olingo/fit/tecsvc/http/EntityReferenceITCase.java
new file mode 100644
index 0000000..bcfc096
--- /dev/null
+++ 
b/fit/src/test/java/org/apache/olingo/fit/tecsvc/http/EntityReferenceITCase.java
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.olingo.fit.tecsvc.http;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.URL;
+
+import org.apache.olingo.client.api.ODataClient;
+import org.apache.olingo.commons.api.http.HttpHeader;
+import org.apache.olingo.fit.AbstractBaseTestITCase;
+import org.apache.olingo.fit.tecsvc.TecSvcConst;
+import 
org.apache.olingo.server.core.deserializer.batch.BufferedReaderIncludingLineEndings;
+import org.junit.Test;
+
+public class EntityReferenceITCase extends AbstractBaseTestITCase {
+
+  private static final String CONTEXT_ENTITY_REFERENCE = 
"\"@odata.context\":\"$metadata#$ref\"";
+  private static final String CONTEXT_COLLECTION_REFERENCE = 
"\"@odata.context\":\"$metadata#Collection($ref)";
+  private static final String SERVICE_URI = TecSvcConst.BASE_URI;
+
+  @Test
+  public void testContextURlSingleEntity() throws Exception {
+      URL url = new URL(SERVICE_URI + "/ESAllPrim(0)/$ref");
+
+      HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+      connection.setRequestProperty(HttpHeader.ACCEPT, "application/json");
+      connection.setRequestMethod("GET");
+      connection.connect();
+
+      int code = connection.getResponseCode();
+      assertEquals(200, code);
+      
+      final String content = getString(connection.getInputStream());
+      assertTrue(content.contains(CONTEXT_ENTITY_REFERENCE));
+  } 
+
+  @Test
+  public void testContextURLEntityCollection() throws Exception {
+    URL url = new URL(SERVICE_URI + "/ESAllPrim/$ref");
+
+    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+    connection.setRequestProperty(HttpHeader.ACCEPT, "application/json");
+    connection.setRequestMethod("GET");
+    connection.connect();
+
+    int code = connection.getResponseCode();
+    assertEquals(200, code);
+    
+    final String content = getString(connection.getInputStream());
+    assertTrue(content.contains(CONTEXT_COLLECTION_REFERENCE));
+  }
+  
+  private String getString(final InputStream in) throws Exception {
+    final StringBuilder builder = new StringBuilder();
+    final BufferedReaderIncludingLineEndings reader = new 
BufferedReaderIncludingLineEndings(new InputStreamReader(in));
+    
+    String line;
+    while((line = reader.readLine()) != null) {
+      builder.append(line);
+    }
+     
+    reader.close();
+    return builder.toString();
+  }
+  
+  @Override
+  protected ODataClient getClient() {
+    return null;
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a2a07242/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/ODataSerializer.java
----------------------------------------------------------------------
diff --git 
a/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/ODataSerializer.java
 
b/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/ODataSerializer.java
index dfec888..470d090 100644
--- 
a/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/ODataSerializer.java
+++ 
b/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/ODataSerializer.java
@@ -18,11 +18,13 @@
  */
 package org.apache.olingo.server.api.serializer;
 
+import org.apache.olingo.commons.api.data.ContextURL;
 import org.apache.olingo.commons.api.data.Entity;
 import org.apache.olingo.commons.api.data.EntityCollection;
 import org.apache.olingo.commons.api.data.Property;
 import org.apache.olingo.commons.api.edm.Edm;
 import org.apache.olingo.commons.api.edm.EdmComplexType;
+import org.apache.olingo.commons.api.edm.EdmEntitySet;
 import org.apache.olingo.commons.api.edm.EdmEntityType;
 import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
 import org.apache.olingo.server.api.ODataServerError;
@@ -111,4 +113,30 @@ public interface ODataSerializer {
    */
   SerializerResult complexCollection(ServiceMetadata metadata, EdmComplexType 
type, Property property,
       ComplexSerializerOptions options) throws SerializerException;
+  
+  /**
+   * Writes a single entity reference into an InputStream
+   * 
+   * @param metadata              Metadata for the service
+   * @param edmEntitySet          {@link EdmEntitySet}
+   * @param entity                data of the entity
+   * @param contextUrl            {@link ContextURL}
+   * @return Serialized           entity reference
+   * @throws SerializerException
+   */
+  SerializerResult reference(ServiceMetadata metadata, EdmEntitySet 
edmEntitySet, Entity entity, 
+      final ContextURL contextUrl) throws SerializerException;
+  
+  /**
+   * Writes entity collection references into an InputStream
+   * 
+   * @param metadata              Metadata for the service
+   * @param edmEntitySet          {@link EdmEntitySet}
+   * @param entityCollection      data of the entity collection
+   * @param contextURL 
+   * @return Serialized           entity reference
+   * @throws SerializerException
+   */
+  SerializerResult referenceCollection(ServiceMetadata metadata, EdmEntitySet 
edmEntitySet, 
+      EntityCollection entityCollection, final ContextURL contextURL) throws 
SerializerException;
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a2a07242/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 7650894..65ad204 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
@@ -33,6 +33,7 @@ import org.apache.olingo.commons.api.data.Linked;
 import org.apache.olingo.commons.api.data.Property;
 import org.apache.olingo.commons.api.edm.Edm;
 import org.apache.olingo.commons.api.edm.EdmComplexType;
+import org.apache.olingo.commons.api.edm.EdmEntitySet;
 import org.apache.olingo.commons.api.edm.EdmEntityType;
 import org.apache.olingo.commons.api.edm.EdmNavigationProperty;
 import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
@@ -52,6 +53,7 @@ import 
org.apache.olingo.server.api.serializer.ODataSerializer;
 import org.apache.olingo.server.api.serializer.PrimitiveSerializerOptions;
 import org.apache.olingo.server.api.serializer.SerializerException;
 import org.apache.olingo.server.api.serializer.SerializerResult;
+import org.apache.olingo.server.api.uri.UriHelper;
 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;
@@ -59,6 +61,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.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -145,7 +148,7 @@ public class ODataJsonSerializer implements ODataSerializer 
{
 
       if (options != null && options.getCount() != null && 
options.getCount().getValue()
           && entitySet.getCount() != null) {
-        json.writeNumberField(Constants.JSON_COUNT, entitySet.getCount());
+        writeCount(entitySet, json);
       }
       json.writeFieldName(Constants.VALUE);
       if (options == null) {
@@ -155,7 +158,7 @@ public class ODataJsonSerializer implements ODataSerializer 
{
             options.getExpand(), options.getSelect(), 
options.onlyReferences(), json);
       }
       if (entitySet.getNext() != null) {
-        json.writeStringField(Constants.JSON_NEXT_LINK, 
entitySet.getNext().toASCIIString());
+        writeNextLink(entitySet, json);
       }
       json.close();
     } catch (final IOException e) {
@@ -639,4 +642,87 @@ public class ODataJsonSerializer implements 
ODataSerializer {
     }
     return 
SerializerResultImpl.with().content(buffer.getInputStream()).build();
   }
+
+  @Override
+  public SerializerResult reference(final ServiceMetadata metadata, final 
EdmEntitySet edmEntitySet, 
+      final Entity entity, final ContextURL contextURL) throws 
SerializerException {
+    
+    final CircleStreamBuffer buffer = new CircleStreamBuffer();
+    final UriHelper uriHelper = new UriHelperImpl();
+    
+    try {
+      final JsonGenerator json = new 
JsonFactory().createGenerator(buffer.getOutputStream());
+      writeReference(edmEntitySet, entity, contextURL, uriHelper, json);
+      
+      json.close();
+    } catch (IOException e) {
+      throw new SerializerException("An I/O exception occurred.", e,  
SerializerException.MessageKeys.IO_EXCEPTION);
+    }
+    
+    return 
SerializerResultImpl.with().content(buffer.getInputStream()).build();
+  }
+  
+  @Override
+  public SerializerResult referenceCollection(final ServiceMetadata metadata, 
final EdmEntitySet edmEntitySet, 
+      final EntityCollection entityCollection, final ContextURL contextURL) 
throws SerializerException {
+    
+    final CircleStreamBuffer buffer = new CircleStreamBuffer();
+    final UriHelper uriHelper = new UriHelperImpl();
+    
+    try {
+      final JsonGenerator json = new 
JsonFactory().createGenerator(buffer.getOutputStream());
+      json.writeStartObject();
+      
+      if(entityCollection.getCount() != null) {
+        writeCount(entityCollection, json);
+      }
+      
+      json.writeStringField(Constants.JSON_CONTEXT, 
ContextURLBuilder.create(contextURL).toASCIIString());
+      writeReferenceCollection(metadata, edmEntitySet, entityCollection, 
uriHelper,json);
+      
+      if(entityCollection.getNext() != null) {
+        writeNextLink(entityCollection, json);
+      }
+      
+      json.writeEndObject();
+      json.close();
+    } catch (IOException e) {
+      throw new SerializerException("An I/O exception occurred.", e,  
SerializerException.MessageKeys.IO_EXCEPTION);
+    }
+    
+    return 
SerializerResultImpl.with().content(buffer.getInputStream()).build();
+  }
+
+  protected void writeReferenceCollection(final ServiceMetadata metadata, 
final EdmEntitySet edmEntitySet, 
+      final EntityCollection entityCollection, final UriHelper uriHelper, 
final JsonGenerator json) 
+          throws IOException, SerializerException {
+  
+    json.writeArrayFieldStart(Constants.VALUE);
+
+    for(final Entity entity : entityCollection.getEntities()) {
+      writeReference(edmEntitySet, entity, null, uriHelper, json);
+    }
+
+    json.writeEndArray();
+  }
+  
+  protected void writeReference(final EdmEntitySet edmEntitySet, final Entity 
entity, final ContextURL contextURL, 
+      final UriHelper uriHelper, final JsonGenerator json) throws IOException, 
SerializerException {
+    
+    json.writeStartObject();
+    if(contextURL != null) {
+      json.writeStringField(Constants.JSON_CONTEXT, 
ContextURLBuilder.create(contextURL).toASCIIString());
+    }
+    
+    json.writeStringField(Constants.JSON_ID, 
uriHelper.buildCanonicalURL(edmEntitySet, entity));
+    json.writeEndObject();
+  }
+  
+  private void writeCount(final EntityCollection entitySet, JsonGenerator 
json) throws IOException {
+    json.writeNumberField(Constants.JSON_COUNT, entitySet.getCount());
+  }
+
+  private void writeNextLink(final EntityCollection entitySet, JsonGenerator 
json) throws IOException {
+    json.writeStringField(Constants.JSON_NEXT_LINK, 
entitySet.getNext().toASCIIString());
+  }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a2a07242/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/xml/ODataXmlSerializerImpl.java
----------------------------------------------------------------------
diff --git 
a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/xml/ODataXmlSerializerImpl.java
 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/xml/ODataXmlSerializerImpl.java
index b15450b..795a330 100644
--- 
a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/xml/ODataXmlSerializerImpl.java
+++ 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/xml/ODataXmlSerializerImpl.java
@@ -22,11 +22,13 @@ import javax.xml.stream.XMLOutputFactory;
 import javax.xml.stream.XMLStreamException;
 import javax.xml.stream.XMLStreamWriter;
 
+import org.apache.olingo.commons.api.data.ContextURL;
 import org.apache.olingo.commons.api.data.Entity;
 import org.apache.olingo.commons.api.data.EntityCollection;
 import org.apache.olingo.commons.api.data.Property;
 import org.apache.olingo.commons.api.edm.Edm;
 import org.apache.olingo.commons.api.edm.EdmComplexType;
+import org.apache.olingo.commons.api.edm.EdmEntitySet;
 import org.apache.olingo.commons.api.edm.EdmEntityType;
 import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
 import org.apache.olingo.server.api.ODataServerError;
@@ -134,4 +136,18 @@ public class ODataXmlSerializerImpl implements 
ODataSerializer {
     throw new SerializerException("Serialization not implemented for XML 
format.",
         SerializerException.MessageKeys.NOT_IMPLEMENTED);
   }
+
+  @Override
+  public SerializerResult reference(final ServiceMetadata metadata, final 
EdmEntitySet edmEntotySet, 
+      final Entity entity, final ContextURL contextURL) throws 
SerializerException {
+    throw new SerializerException("Serialization not implemented for XML 
format.",
+        SerializerException.MessageKeys.NOT_IMPLEMENTED);
+  }
+
+  @Override
+  public SerializerResult referenceCollection(final ServiceMetadata metadata, 
final EdmEntitySet edmEntitySet, 
+      final EntityCollection entityCollection, final ContextURL contextURL) 
throws SerializerException {
+    throw new SerializerException("Serialization not implemented for XML 
format.",
+        SerializerException.MessageKeys.NOT_IMPLEMENTED);
+  }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a2a07242/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 535280b..167a15c 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
@@ -48,6 +48,8 @@ import 
org.apache.olingo.server.api.processor.CountEntityCollectionProcessor;
 import org.apache.olingo.server.api.processor.EntityCollectionProcessor;
 import org.apache.olingo.server.api.processor.EntityProcessor;
 import org.apache.olingo.server.api.processor.MediaEntityProcessor;
+import org.apache.olingo.server.api.processor.ReferenceCollectionProcessor;
+import org.apache.olingo.server.api.processor.ReferenceProcessor;
 import 
org.apache.olingo.server.api.serializer.EntityCollectionSerializerOptions;
 import org.apache.olingo.server.api.serializer.EntitySerializerOptions;
 import org.apache.olingo.server.api.serializer.ODataSerializer;
@@ -57,6 +59,7 @@ import org.apache.olingo.server.api.uri.UriInfo;
 import org.apache.olingo.server.api.uri.UriResourceAction;
 import org.apache.olingo.server.api.uri.UriResourceEntitySet;
 import org.apache.olingo.server.api.uri.UriResourceFunction;
+import org.apache.olingo.server.api.uri.queryoption.CountOption;
 import org.apache.olingo.server.api.uri.queryoption.ExpandOption;
 import org.apache.olingo.server.api.uri.queryoption.SelectOption;
 import org.apache.olingo.server.tecsvc.data.DataProvider;
@@ -76,7 +79,7 @@ import 
org.apache.olingo.server.tecsvc.processor.queryoptions.options.TopHandler
 public class TechnicalEntityProcessor extends TechnicalProcessor
     implements EntityCollectionProcessor, ActionEntityCollectionProcessor, 
CountEntityCollectionProcessor,
     EntityProcessor, ActionEntityProcessor, MediaEntityProcessor,
-    ActionVoidProcessor {
+    ActionVoidProcessor, ReferenceCollectionProcessor, ReferenceProcessor {
 
   public TechnicalEntityProcessor(final DataProvider dataProvider, final 
ServiceMetadata serviceMetadata) {
     super(dataProvider, serviceMetadata);
@@ -87,62 +90,7 @@ public class TechnicalEntityProcessor extends 
TechnicalProcessor
       final ContentType requestedContentType) throws 
ODataApplicationException, SerializerException {
     validateOptions(uriInfo.asUriInfoResource());
 
-    final EdmEntitySet edmEntitySet = 
getEdmEntitySet(uriInfo.asUriInfoResource());
-    final EdmEntityType edmEntityType = edmEntitySet == null ?
-        (EdmEntityType) ((UriResourceFunction) uriInfo.getUriResourceParts()
-            .get(uriInfo.getUriResourceParts().size() - 1)).getType() :
-        edmEntitySet.getEntityType();
-
-    final EntityCollection entitySetInitial = readEntityCollection(uriInfo);
-    if (entitySetInitial == null) {
-      throw new ODataApplicationException("Nothing found.", 
HttpStatusCode.NOT_FOUND.getStatusCode(), Locale.ROOT);
-    } else {
-      // Modifying the original entitySet means modifying the "database", so 
we have to make a shallow
-      // copy of the entity set (new EntitySet, but exactly the same data)
-      EntityCollection entitySet = new EntityCollection();
-      entitySet.getEntities().addAll(entitySetInitial.getEntities());
-
-      // Apply system query options
-      FilterHandler.applyFilterSystemQuery(uriInfo.getFilterOption(), 
entitySet, edmEntitySet);
-      CountHandler.applyCountSystemQueryOption(uriInfo.getCountOption(), 
entitySet);
-      OrderByHandler.applyOrderByOption(uriInfo.getOrderByOption(), entitySet, 
edmEntitySet);
-      SkipHandler.applySkipSystemQueryHandler(uriInfo.getSkipOption(), 
entitySet);
-      TopHandler.applyTopSystemQueryOption(uriInfo.getTopOption(), entitySet);
-
-      
ServerSidePagingHandler.applyServerSidePaging(uriInfo.getSkipTokenOption(),
-          entitySet,
-          edmEntitySet,
-          request.getRawRequestUri());
-
-      // Apply expand system query option
-      final ODataFormat format = 
ODataFormat.fromContentType(requestedContentType);
-      ODataSerializer serializer = odata.createSerializer(format);
-      final ExpandOption expand = uriInfo.getExpandOption();
-      final SelectOption select = uriInfo.getSelectOption();
-
-      // Transform the entity graph to a tree. The construction is controlled 
by the expand tree.
-      // Apply all expand system query options to the tree.So the expanded 
navigation properties can be modified
-      // for serialization,without affecting the data stored in the database.
-      final ExpandSystemQueryOptionHandler expandHandler = new 
ExpandSystemQueryOptionHandler();
-      final EntityCollection entitySetSerialization = 
expandHandler.transformEntitySetGraphToTree(entitySet,
-          edmEntitySet,
-          expand);
-      expandHandler.applyExpandQueryOptions(entitySetSerialization, 
edmEntitySet, expand);
-
-      // Serialize
-      response.setContent(serializer.entityCollection(
-          serviceMetadata,
-          edmEntityType,
-          entitySetSerialization,
-          EntityCollectionSerializerOptions.with()
-              .contextURL(format == ODataFormat.JSON_NO_METADATA ? null :
-                  getContextUrl(edmEntitySet, edmEntityType, false, expand, 
select))
-              .count(uriInfo.getCountOption())
-              .expand(expand).select(select)
-              .build()).getContent());
-      response.setStatusCode(HttpStatusCode.OK.getStatusCode());
-      response.setHeader(HttpHeader.CONTENT_TYPE, 
requestedContentType.toContentTypeString());
-    }
+    processEntityCollection(request, response, uriInfo, requestedContentType, 
false);
   }
 
   @Override
@@ -178,7 +126,8 @@ public class TechnicalEntityProcessor extends 
TechnicalProcessor
   }
 
   @Override
-  public void countEntityCollection(final ODataRequest request, final 
ODataResponse response, final UriInfo uriInfo)
+  public void countEntityCollection(final ODataRequest request, final 
ODataResponse response, final UriInfo
+      uriInfo)
       throws ODataApplicationException, SerializerException {
     validateOptions(uriInfo.asUriInfoResource());
     final EdmEntitySet edmEntitySet = getEdmEntitySet(uriInfo); // including 
checks
@@ -200,29 +149,8 @@ public class TechnicalEntityProcessor extends 
TechnicalProcessor
   public void readEntity(final ODataRequest request, final ODataResponse 
response, final UriInfo uriInfo,
       final ContentType requestedContentType) throws 
ODataApplicationException, SerializerException {
     validateOptions(uriInfo.asUriInfoResource());
-    final EdmEntitySet edmEntitySet = getEdmEntitySet(uriInfo);
-    final EdmEntityType edmEntityType = edmEntitySet == null ?
-        (EdmEntityType) ((UriResourceFunction) uriInfo.getUriResourceParts()
-            .get(uriInfo.getUriResourceParts().size() - 1)).getType() :
-        edmEntitySet.getEntityType();
-
-    final Entity entity = readEntity(uriInfo);
-
-    final ODataFormat format = 
ODataFormat.fromContentType(requestedContentType);
-    final ExpandOption expand = uriInfo.getExpandOption();
-    final SelectOption select = uriInfo.getSelectOption();
 
-    final ExpandSystemQueryOptionHandler expandHandler = new 
ExpandSystemQueryOptionHandler();
-    final Entity entitySerialization = 
expandHandler.transformEntityGraphToTree(entity, edmEntitySet, expand);
-    expandHandler.applyExpandQueryOptions(entitySerialization, edmEntitySet, 
expand);
-
-    response.setContent(serializeEntity(entitySerialization, edmEntitySet, 
edmEntityType, format, expand, select)
-        .getContent());
-    response.setStatusCode(HttpStatusCode.OK.getStatusCode());
-    response.setHeader(HttpHeader.CONTENT_TYPE, 
requestedContentType.toContentTypeString());
-    if (entity.getETag() != null) {
-      response.setHeader(HttpHeader.ETAG, entity.getETag());
-    }
+    processEntity(request, response, uriInfo, requestedContentType, false);
   }
 
   @Override
@@ -274,7 +202,9 @@ public class TechnicalEntityProcessor extends 
TechnicalProcessor
           request.getRawBaseUri()).validate(edmEntitySet, 
deserializerResult.getEntity());
 
       entity = dataProvider.create(edmEntitySet);
-      dataProvider.update(request.getRawBaseUri(), edmEntitySet, entity, 
deserializerResult.getEntity(), false, true);
+      dataProvider.update(request.getRawBaseUri(), edmEntitySet, entity, 
deserializerResult.getEntity(), false,
+
+          true);
       expand = deserializerResult.getExpandTree();
     }
 
@@ -390,7 +320,9 @@ public class TechnicalEntityProcessor extends 
TechnicalProcessor
       final ODataFormat format = ODataFormat.fromContentType(responseFormat);
       response.setContent(serializeEntity(entityResult.getEntity(), 
edmEntitySet, type, format, null, null)
           .getContent());
-      response.setStatusCode((entityResult.isCreated() ? 
HttpStatusCode.CREATED : HttpStatusCode.OK).getStatusCode());
+      response.setStatusCode((entityResult.isCreated() ? 
HttpStatusCode.CREATED : HttpStatusCode.OK).getStatusCode
+
+          ());
       response.setHeader(HttpHeader.CONTENT_TYPE, 
responseFormat.toContentTypeString());
       if (entityResult.getEntity().getETag() != null) {
         response.setHeader(HttpHeader.ETAG, 
entityResult.getEntity().getETag());
@@ -420,7 +352,9 @@ public class TechnicalEntityProcessor extends 
TechnicalProcessor
   }
 
   private ContextURL getContextUrl(final EdmEntitySet entitySet, final 
EdmEntityType entityType,
-      final boolean isSingleEntity, final ExpandOption expand, final 
SelectOption select) throws SerializerException {
+      final boolean isSingleEntity, final ExpandOption expand, final 
SelectOption select) throws
+
+      SerializerException {
     Builder builder = ContextURL.with();
     builder = entitySet == null ?
         isSingleEntity ? builder.type(entityType) : 
builder.asCollection().type(entityType) :
@@ -431,9 +365,170 @@ public class TechnicalEntityProcessor extends 
TechnicalProcessor
     return builder.build();
   }
 
+  @Override
+  public void readReference(final ODataRequest request, final ODataResponse 
response, final UriInfo uriInfo, 
+      final ContentType requestedContentType) throws 
ODataApplicationException, SerializerException {
+    
+    processEntity(request, response, uriInfo, requestedContentType, true);
+  }
+
+  @Override
+  public void createReference(final ODataRequest request, final ODataResponse 
response, final UriInfo uriInfo, 
+      final ContentType requestFormat) throws ODataApplicationException, 
DeserializerException {
+    
+    throw new ODataApplicationException("Not implemented", 
HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT);
+  }
+
+  @Override
+  public void updateReference(final ODataRequest request, final ODataResponse 
response, final UriInfo uriInfo, 
+      final ContentType requestFormat) throws ODataApplicationException, 
DeserializerException {
+    
+    throw new ODataApplicationException("Not implemented", 
HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT);
+  }
+
+  @Override
+  public void deleteReference(final ODataRequest request, final ODataResponse 
response, final UriInfo uriInfo) 
+      throws ODataApplicationException {
+    
+    throw new ODataApplicationException("Not implemented", 
HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT);
+  }
+
+  @Override
+  public void readReferenceCollection(final ODataRequest request, final 
ODataResponse response, final UriInfo uriInfo, 
+      final ContentType requestedContentType) throws 
ODataApplicationException, SerializerException {
+  
+    processEntityCollection(request, response, uriInfo, requestedContentType, 
true);
+  }
+
+  private void processEntity(final ODataRequest request, final ODataResponse 
response, final UriInfo uriInfo, 
+      final ContentType requestedContentType, final boolean isReference)
+      throws ODataApplicationException, SerializerException {
+    final EdmEntitySet edmEntitySet = getEdmEntitySet(uriInfo);
+    final EdmEntityType edmEntityType = edmEntitySet == null ?
+        (EdmEntityType) ((UriResourceFunction) uriInfo.getUriResourceParts()
+            .get(uriInfo.getUriResourceParts().size() - 1)).getType() :
+        edmEntitySet.getEntityType();
+
+    final Entity entity = readEntity(uriInfo);
+
+    final ODataFormat format = 
ODataFormat.fromContentType(requestedContentType);
+    final ExpandOption expand = uriInfo.getExpandOption();
+    final SelectOption select = uriInfo.getSelectOption();
+
+    final ExpandSystemQueryOptionHandler expandHandler = new 
ExpandSystemQueryOptionHandler();
+    final Entity entitySerialization = 
expandHandler.transformEntityGraphToTree(entity, edmEntitySet, expand);
+    expandHandler.applyExpandQueryOptions(entitySerialization, edmEntitySet, 
expand);
+    
+    final SerializerResult serializerResult = (isReference) ? 
+          serializeReference(entity, edmEntitySet, format) 
+        : serializeEntity(entitySerialization, edmEntitySet, edmEntityType, 
format, expand, select);
+    
+          
+    if (entity.getETag() != null) {
+      response.setHeader(HttpHeader.ETAG, entity.getETag());
+    }
+    response.setContent(serializerResult.getContent());
+    response.setStatusCode(HttpStatusCode.OK.getStatusCode());
+    response.setHeader(HttpHeader.CONTENT_TYPE, 
requestedContentType.toContentTypeString());
+  }
+  
+  private void processEntityCollection(final ODataRequest request, final 
ODataResponse response, 
+      final UriInfo uriInfo, final ContentType requestedContentType, final 
boolean isReference) 
+          throws ODataApplicationException, SerializerException {
+    
+    final EdmEntitySet edmEntitySet = 
getEdmEntitySet(uriInfo.asUriInfoResource());
+    final EdmEntityType edmEntityType = edmEntitySet == null ?
+        (EdmEntityType) ((UriResourceFunction) uriInfo.getUriResourceParts()
+            .get(uriInfo.getUriResourceParts().size() - 1)).getType() :
+        edmEntitySet.getEntityType();
+
+    EntityCollection entitySetInitial = readEntityCollection(uriInfo);
+    if(entitySetInitial == null) {
+      entitySetInitial = new EntityCollection();
+    }
+    
+    // Modifying the original entitySet means modifying the "database", so we 
have to make a shallow
+    // copy of the entity set (new EntitySet, but exactly the same data)
+    EntityCollection entitySet = new EntityCollection();
+    entitySet.getEntities().addAll(entitySetInitial.getEntities());
+
+    // Apply system query options
+    FilterHandler.applyFilterSystemQuery(uriInfo.getFilterOption(), entitySet, 
edmEntitySet);
+    CountHandler.applyCountSystemQueryOption(uriInfo.getCountOption(), 
entitySet);
+    OrderByHandler.applyOrderByOption(uriInfo.getOrderByOption(), entitySet, 
edmEntitySet);
+    SkipHandler.applySkipSystemQueryHandler(uriInfo.getSkipOption(), 
entitySet);
+    TopHandler.applyTopSystemQueryOption(uriInfo.getTopOption(), entitySet);
+
+    ServerSidePagingHandler.applyServerSidePaging(uriInfo.getSkipTokenOption(),
+        entitySet,
+        edmEntitySet,
+        request.getRawRequestUri());
+
+    // Apply expand system query option
+    final ODataFormat format = 
ODataFormat.fromContentType(requestedContentType);
+    final ExpandOption expand = uriInfo.getExpandOption();
+    final SelectOption select = uriInfo.getSelectOption();
+
+    // Transform the entity graph to a tree. The construction is controlled by 
the expand tree.
+    // Apply all expand system query options to the tree.So the expanded 
navigation properties can be modified
+    // for serialization,without affecting the data stored in the database.
+    final ExpandSystemQueryOptionHandler expandHandler = new 
ExpandSystemQueryOptionHandler();
+    final EntityCollection entitySetSerialization = 
expandHandler.transformEntitySetGraphToTree(entitySet,
+        edmEntitySet,
+        expand);
+    expandHandler.applyExpandQueryOptions(entitySetSerialization, 
edmEntitySet, expand);
+    final CountOption countOption = uriInfo.getCountOption();
+    
+    // Serialize
+    final SerializerResult serializerResult = (isReference) ? 
+        serializeReferenceCollection(entitySetSerialization, edmEntitySet, 
format) :
+          serializeEntiyCollection(entitySetSerialization, edmEntitySet, 
edmEntityType, format, 
+                                   expand, select, countOption);
+    
+    response.setContent(serializerResult.getContent());
+    response.setStatusCode(HttpStatusCode.OK.getStatusCode());
+    response.setHeader(HttpHeader.CONTENT_TYPE, 
requestedContentType.toContentTypeString());
+  }
+
+  private SerializerResult serializeEntiyCollection(final EntityCollection 
entityCollection, 
+      final EdmEntitySet edmEntitySet, final EdmEntityType edmEntityType, 
final ODataFormat format, 
+      final ExpandOption expand, final SelectOption select, final CountOption 
countOption) 
+          throws SerializerException {
+    
+    return odata.createSerializer(format).entityCollection(
+        serviceMetadata,
+        edmEntityType,
+        entityCollection,
+        EntityCollectionSerializerOptions.with()
+            .contextURL(format == ODataFormat.JSON_NO_METADATA ? null :
+                getContextUrl(edmEntitySet, edmEntityType, false, expand, 
select))
+            .count(countOption)
+            .expand(expand).select(select)
+            .build());
+  }
+  
+  private SerializerResult serializeReferenceCollection(final EntityCollection 
entityCollection, 
+      final EdmEntitySet edmEntitySet, final ODataFormat format) throws 
SerializerException {
+    
+    final ContextURL contextUrl = 
ContextURL.with().asCollection().suffix(Suffix.REFERENCE).build();
+    final ODataSerializer serializer = odata.createSerializer(format);
+    
+    return serializer.referenceCollection(serviceMetadata, edmEntitySet, 
entityCollection, contextUrl);
+  }
+  
+  private SerializerResult serializeReference(final Entity entity, final 
EdmEntitySet edmEntitySet, 
+      final ODataFormat format ) throws SerializerException {
+    
+    final ContextURL contextUrl = 
ContextURL.with().suffix(Suffix.REFERENCE).build();
+    final ODataSerializer serializer = odata.createSerializer(format);
+    
+    return serializer.reference(serviceMetadata, edmEntitySet, entity, 
contextUrl);
+  }
+  
   private SerializerResult serializeEntity(final Entity entity,
       final EdmEntitySet edmEntitySet, final EdmEntityType edmEntityType, 
final ODataFormat format,
       final ExpandOption expand, final SelectOption select) throws 
SerializerException {
+    
     return odata.createSerializer(format).entity(
         serviceMetadata,
         edmEntityType,

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a2a07242/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 2e42963..c867022 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
@@ -48,6 +48,7 @@ import 
org.apache.olingo.server.api.serializer.EntitySerializerOptions;
 import org.apache.olingo.server.api.serializer.ODataSerializer;
 import org.apache.olingo.server.api.serializer.PrimitiveSerializerOptions;
 import org.apache.olingo.server.api.serializer.SerializerException;
+import org.apache.olingo.server.api.serializer.SerializerResult;
 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;
@@ -681,4 +682,50 @@ public class ODataJsonSerializerTest {
         + "{\"PropertyInt16\":789,\"PropertyString\":\"TEST 3\"}]}",
         resultString);
   }
+  
+  @Test
+  public void entityReference() throws Exception {
+    final EdmEntitySet edmEntitySet = 
entityContainer.getEntitySet("ESAllPrim");
+    final Entity entity = data.readAll(edmEntitySet).getEntities().get(0);
+    
+    final SerializerResult serializerResult = serializer.reference(metadata, 
edmEntitySet, entity,
+        ContextURL.with().suffix(Suffix.REFERENCE).build());
+    final String resultString = 
IOUtils.toString(serializerResult.getContent());
+    
+    
Assert.assertEquals("{\"@odata.context\":\"$metadata#$ref\",\"@odata.id\":\"ESAllPrim(32767)\"}",
 resultString);
+  }
+  
+  @Test
+  public void entityCollectionReference() throws Exception {
+    final EdmEntitySet edmEntitySet = 
entityContainer.getEntitySet("ESAllPrim");
+    final EntityCollection entityCollection = data.readAll(edmEntitySet);
+
+    final SerializerResult serializerResult = 
serializer.referenceCollection(metadata, 
+                                                                             
edmEntitySet, 
+                                                                             
entityCollection,
+                                                                             
ContextURL.with().asCollection()
+                                                                               
  .suffix(Suffix.REFERENCE).build());
+                                                                               
  
+    final String resultString = 
IOUtils.toString(serializerResult.getContent());
+
+    
Assert.assertEquals("{\"@odata.context\":\"$metadata#Collection($ref)\",\"value\":[{\"@odata.id\":"
 + 
+                         
"\"ESAllPrim(32767)\"},{\"@odata.id\":\"ESAllPrim(-32768)\"},{\"@odata.id\":" + 
+                         "\"ESAllPrim(0)\"}]}", resultString);
+  }
+  
+  @Test
+  public void entityCollectionReferenceEmpty() throws Exception {
+    final EdmEntitySet edmEntitySet = 
entityContainer.getEntitySet("ESAllPrim");
+    final EntityCollection entityCollection = new EntityCollection();
+    
+    final SerializerResult serializerResult = 
serializer.referenceCollection(metadata, 
+                                                                             
edmEntitySet, 
+                                                                             
entityCollection,
+                                                                             
ContextURL.with().asCollection()
+                                                                             
.suffix(Suffix.REFERENCE).build());
+    
+    final String resultString = 
IOUtils.toString(serializerResult.getContent());
+
+    
Assert.assertEquals("{\"@odata.context\":\"$metadata#Collection($ref)\",\"value\":[]}",
 resultString);
+  }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a2a07242/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestFullResourcePath.java
----------------------------------------------------------------------
diff --git 
a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestFullResourcePath.java
 
b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestFullResourcePath.java
index 989b058..f5e625a 100644
--- 
a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestFullResourcePath.java
+++ 
b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestFullResourcePath.java
@@ -4756,8 +4756,9 @@ public class TestFullResourcePath {
             .root().right().goPath()
             .first().isComplex("PropertyCompMixedEnumDef")
             
.n().isComplex("PropertyEnumString").isType(EnumTypeProvider.nameENString).goUpFilterValidator();
-  }
 
+  }
+  
   @Test
   public void filterOnCountAndRef() throws Exception {
     testUri.run("ESKeyNav/$count", "$filter=PropertyInt16 ge 0")
@@ -4771,7 +4772,7 @@ public class TestFullResourcePath {
         .left().goPath().first().isPrimitiveProperty("PropertyInt16", 
PropertyProvider.nameInt16, false)
         .goUpFilterValidator().root().right().isLiteral("0");
   }
-
+  
   @Test
   public void testOrderby() throws UriParserException, 
UnsupportedEncodingException {
 

Reply via email to