You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by mi...@apache.org on 2016/02/13 07:33:55 UTC

[01/22] olingo-odata4 git commit: OLINGO-855: adding support for odata-isolation header support acknowledgement to ServiceHandler interface

Repository: olingo-odata4
Updated Branches:
  refs/heads/OLINGO-832_StreamSerializerPoC 5174f7089 -> 67494a789


OLINGO-855: adding support for odata-isolation header support acknowledgement to ServiceHandler interface


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

Branch: refs/heads/OLINGO-832_StreamSerializerPoC
Commit: b317b9006d9a71c58a5b4a0f62558b11acba3dae
Parents: b9512ed
Author: Ramesh Reddy <ra...@jboss.org>
Authored: Mon Jan 25 09:20:54 2016 -0600
Committer: Ramesh Reddy <ra...@jboss.org>
Committed: Mon Jan 25 09:20:54 2016 -0600

----------------------------------------------------------------------
 .../apache/olingo/commons/api/http/HttpHeader.java    |  2 ++
 .../apache/olingo/server/core/ServiceDispatcher.java  |  9 +++++++++
 .../org/apache/olingo/server/core/ServiceHandler.java | 14 ++++++++++++++
 .../server/core/legacy/ProcessorServiceHandler.java   |  5 +++++
 .../apache/olingo/server/example/TripPinHandler.java  |  5 +++++
 .../olingo/server/example/TripPinServiceTest.java     | 10 ++++++++++
 6 files changed, 45 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b317b900/lib/commons-api/src/main/java/org/apache/olingo/commons/api/http/HttpHeader.java
----------------------------------------------------------------------
diff --git a/lib/commons-api/src/main/java/org/apache/olingo/commons/api/http/HttpHeader.java b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/http/HttpHeader.java
index f33dbb0..91c65ca 100644
--- a/lib/commons-api/src/main/java/org/apache/olingo/commons/api/http/HttpHeader.java
+++ b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/http/HttpHeader.java
@@ -176,4 +176,6 @@ public interface HttpHeader {
   String ODATA_MAX_VERSION = "OData-MaxVersion";
   /** Custom Header defined in the OData standard. */
   String ODATA_ENTITY_ID = "OData-EntityID";
+  /** Custom Header defined in the OData standard. */
+  String ODATA_ISOLATION= "OData-Isolation";
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b317b900/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ServiceDispatcher.java
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ServiceDispatcher.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ServiceDispatcher.java
index 45de757..cb718e1 100644
--- a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ServiceDispatcher.java
+++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ServiceDispatcher.java
@@ -24,6 +24,8 @@ import java.net.URISyntaxException;
 import java.net.URL;
 
 import org.apache.olingo.commons.api.format.ContentType;
+import org.apache.olingo.commons.api.http.HttpHeader;
+import org.apache.olingo.commons.api.http.HttpStatusCode;
 import org.apache.olingo.server.api.OData;
 import org.apache.olingo.server.api.ODataApplicationException;
 import org.apache.olingo.server.api.ODataRequest;
@@ -81,6 +83,13 @@ public class ServiceDispatcher extends RequestURLHierarchyVisitor {
 
     new UriValidator().validate(uriInfo, odRequest.getMethod());
 
+    // part1, 8.2.6
+    String isolation = odRequest.getHeader(HttpHeader.ODATA_ISOLATION);
+    if (isolation != null && isolation.equals("snapshot") && !this.handler.supportsDataIsolation()) {
+      odResponse.setStatusCode(HttpStatusCode.PRECONDITION_FAILED.getStatusCode());
+      return;
+    }
+    
     visit(uriInfo);
 
     // this should cover for any unsupported calls until they are implemented

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b317b900/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ServiceHandler.java
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ServiceHandler.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ServiceHandler.java
index 68043de..ba96f94 100644
--- a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ServiceHandler.java
+++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ServiceHandler.java
@@ -282,4 +282,18 @@ public interface ServiceHandler extends Processor {
    */
   void crossJoin(DataRequest dataRequest, List<String> entitySetNames, ODataResponse response)
       throws ODataLibraryException, ODataApplicationException;
+  
+  /**
+   * Snapshot isolation guarantees that all data returned for a request, including multiple requests within 
+   * a batch or results retrieved across multiple pages, will be consistent as of a single point in time. 
+   * Only data modifications made within the request (for example, by a data modification request 
+   * within the same batch) are visible. The effect is as if the request generates a "snapshot" of 
+   * the committed data as it existed at the start of the request. for more info see OData V4, Part1 8.2.6
+   * 
+   * The contract for this interface is if it returns true, whenever the service deals with $skiptoken based
+   * results, they MUST be from same snapshot of the original request. false, the framework will automatically
+   * returns a 412.
+   * @return
+   */
+  boolean supportsDataIsolation();
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b317b900/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/legacy/ProcessorServiceHandler.java
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/legacy/ProcessorServiceHandler.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/legacy/ProcessorServiceHandler.java
index b65f19c..db62c0a 100644
--- a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/legacy/ProcessorServiceHandler.java
+++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/legacy/ProcessorServiceHandler.java
@@ -437,4 +437,9 @@ public class ProcessorServiceHandler implements ServiceHandler {
     throw new ODataHandlerException("not implemented",
         ODataHandlerException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED);
   }
+
+  @Override
+  public boolean supportsDataIsolation() {
+    return false;
+  }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b317b900/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinHandler.java
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinHandler.java b/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinHandler.java
index db06558..fea02e9 100644
--- a/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinHandler.java
+++ b/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinHandler.java
@@ -556,4 +556,9 @@ public class TripPinHandler implements ServiceHandler {
       updateEntity(request, entity, merge, entityETag, response);
     }
   }
+
+  @Override
+  public boolean supportsDataIsolation() {
+    return false;
+  }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b317b900/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinServiceTest.java
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinServiceTest.java b/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinServiceTest.java
index ef5376d..3beb274 100644
--- a/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinServiceTest.java
+++ b/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinServiceTest.java
@@ -42,6 +42,7 @@ import org.apache.http.entity.ContentType;
 import org.apache.http.entity.StringEntity;
 import org.apache.http.impl.client.DefaultHttpClient;
 import org.apache.http.util.EntityUtils;
+import org.apache.olingo.commons.api.http.HttpHeader;
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
 import org.junit.Ignore;
@@ -732,4 +733,13 @@ public class TripPinServiceTest {
     HttpResponse response = httpGET(editUrl, 200);
     EntityUtils.consumeQuietly(response.getEntity());
   }
+  
+  @Test
+  public void dataIsolation() throws Exception {
+    String url = baseURL + "/People";
+    HttpRequest request = new HttpGet(url);
+    request.setHeader(HttpHeader.ODATA_ISOLATION, "snapshot");
+    HttpResponse response = httpSend(request, 412);
+    EntityUtils.consumeQuietly(response.getEntity());
+  }  
 }


[17/22] olingo-odata4 git commit: OLINGO-874: Error handling improvements

Posted by mi...@apache.org.
OLINGO-874: Error handling improvements


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

Branch: refs/heads/OLINGO-832_StreamSerializerPoC
Commit: 7a68ae68ad72f13927814700be0debc3b481f008
Parents: b7005b7
Author: Ramesh Reddy <ra...@jboss.org>
Authored: Tue Feb 9 13:10:02 2016 -0600
Committer: Ramesh Reddy <ra...@jboss.org>
Committed: Tue Feb 9 14:44:02 2016 -0600

----------------------------------------------------------------------
 .../apache/olingo/server/core/ErrorHandler.java | 47 ++++++----------
 .../olingo/server/core/OData4HttpHandler.java   | 10 ++--
 .../olingo/server/core/ServiceDispatcher.java   | 39 +++++++++++--
 .../olingo/server/core/ServiceHandler.java      | 13 ++++-
 .../core/legacy/ProcessorServiceHandler.java    |  7 +++
 .../server/core/requests/BatchRequest.java      | 11 +---
 .../server/core/responses/EntityResponse.java   |  1 +
 .../core/responses/EntitySetResponse.java       |  2 +
 .../server/core/responses/ErrorResponse.java    | 58 ++++++++++++++++++++
 .../server/core/responses/MetadataResponse.java |  2 +
 .../server/core/responses/PropertyResponse.java |  2 +
 .../core/responses/ServiceDocumentResponse.java |  2 +
 .../core/responses/ServiceResponseVisior.java   |  4 ++
 .../olingo/server/example/TripPinHandler.java   |  9 ++-
 14 files changed, 155 insertions(+), 52 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7a68ae68/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ErrorHandler.java
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ErrorHandler.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ErrorHandler.java
index 33f65cd..bfccc68 100644
--- a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ErrorHandler.java
+++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ErrorHandler.java
@@ -24,18 +24,16 @@ import org.apache.olingo.commons.api.format.ContentType;
 import org.apache.olingo.commons.api.http.HttpHeader;
 import org.apache.olingo.commons.api.http.HttpStatusCode;
 import org.apache.olingo.server.api.OData;
+import org.apache.olingo.server.api.ODataApplicationException;
 import org.apache.olingo.server.api.ODataRequest;
 import org.apache.olingo.server.api.ODataResponse;
 import org.apache.olingo.server.api.ODataServerError;
 import org.apache.olingo.server.api.ServiceMetadata;
 import org.apache.olingo.server.api.deserializer.DeserializerException;
 import org.apache.olingo.server.api.deserializer.batch.BatchDeserializerException;
-import org.apache.olingo.server.api.serializer.CustomContentTypeSupport;
 import org.apache.olingo.server.api.serializer.ODataSerializer;
-import org.apache.olingo.server.api.serializer.RepresentationType;
 import org.apache.olingo.server.api.serializer.SerializerException;
-import org.apache.olingo.server.api.uri.UriInfo;
-import org.apache.olingo.server.core.uri.parser.Parser;
+import org.apache.olingo.server.core.responses.ErrorResponse;
 import org.apache.olingo.server.core.uri.parser.UriParserException;
 import org.apache.olingo.server.core.uri.parser.UriParserSemanticException;
 import org.apache.olingo.server.core.uri.parser.UriParserSyntaxException;
@@ -43,13 +41,16 @@ import org.apache.olingo.server.core.uri.validator.UriValidationException;
 
 public class ErrorHandler {
   private final OData odata;
+  private final ServiceHandler handler;
+  private final ContentType contentType;
   private final ServiceMetadata metadata;
-  private final CustomContentTypeSupport customContent;
-
-  public ErrorHandler(OData odata, ServiceMetadata metadata, CustomContentTypeSupport customContent) {
+  
+  public ErrorHandler(OData odata, ServiceMetadata metadata,
+      ServiceHandler handler, ContentType contentType) {
     this.odata = odata;
+    this.handler = handler;
+    this.contentType = contentType;
     this.metadata = metadata;
-    this.customContent = customContent;
   }
 
   public void handleException(Exception e, ODataRequest request, ODataResponse response) {
@@ -80,7 +81,10 @@ public class ErrorHandler {
     } else if(e instanceof ODataHandlerException) {
       ODataServerError serverError = ODataExceptionHelper.createServerErrorObject((ODataHandlerException)e, null);
       handleServerError(request, response, serverError);
-    } else {
+    } else if(e instanceof ODataApplicationException) {
+      ODataServerError serverError = ODataExceptionHelper.createServerErrorObject((ODataApplicationException)e);
+      handleServerError(request, response, serverError);
+    }else {
       ODataServerError serverError = ODataExceptionHelper.createServerErrorObject(e);
       handleServerError(request, response, serverError);
     }
@@ -88,29 +92,10 @@ public class ErrorHandler {
 
   void handleServerError(final ODataRequest request, final ODataResponse response,
       final ODataServerError serverError) {
-    ContentType requestedContentType;
-    try {
-      final UriInfo uriInfo = new Parser(metadata.getEdm(), odata)
-          .parseUri(request.getRawODataPath(), request.getRawQueryPath(), null);
-      requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
-          request, this.customContent, RepresentationType.ERROR);
-    } catch (final ContentNegotiatorException e) {
-      requestedContentType = ContentType.JSON;
-    } catch (final UriParserException e) {
-      requestedContentType = ContentType.JSON;
-    } catch (final UriValidationException e) {
-      requestedContentType = ContentType.JSON;
-    }
-    processError(response, serverError, requestedContentType);
-  }
-
-  void processError(ODataResponse response, ODataServerError serverError,
-      ContentType requestedContentType) {
     try {
-      ODataSerializer serializer = this.odata.createSerializer(requestedContentType);
-      response.setContent(serializer.error(serverError).getContent());
-      response.setStatusCode(serverError.getStatusCode());
-      response.setHeader(HttpHeader.CONTENT_TYPE, requestedContentType.toContentTypeString());
+      ODataSerializer serializer = this.odata.createSerializer(this.contentType);
+      ErrorResponse errorResponse = new ErrorResponse(this.metadata, serializer, this.contentType, response);
+      handler.processError(serverError, errorResponse);
     } catch (Exception e) {
       // This should never happen but to be sure we have this catch here
       // to prevent sending a stacktrace to a client.

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7a68ae68/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/OData4HttpHandler.java
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/OData4HttpHandler.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/OData4HttpHandler.java
index 7811cdf..18e1364 100644
--- a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/OData4HttpHandler.java
+++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/OData4HttpHandler.java
@@ -24,11 +24,12 @@ import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
 import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion;
+import org.apache.olingo.commons.api.format.ContentType;
 import org.apache.olingo.commons.api.http.HttpHeader;
 import org.apache.olingo.server.api.OData;
+import org.apache.olingo.server.api.ODataLibraryException;
 import org.apache.olingo.server.api.ODataRequest;
 import org.apache.olingo.server.api.ODataResponse;
-import org.apache.olingo.server.api.ODataLibraryException;
 import org.apache.olingo.server.api.ServiceMetadata;
 import org.apache.olingo.server.api.processor.Processor;
 import org.apache.olingo.server.api.serializer.CustomContentTypeSupport;
@@ -63,12 +64,13 @@ public class OData4HttpHandler extends ODataHttpHandlerImpl {
       ServiceDispatcher dispatcher = new ServiceDispatcher(this.odata, this.serviceMetadata,
           handler, this.customContentTypeSupport);
       dispatcher.execute(request, response);
-
+      
     } catch (Exception e) {
+      // also handle any unchecked exception thrown by service handler for proper serialization
       ErrorHandler handler = new ErrorHandler(this.odata, this.serviceMetadata,
-          this.customContentTypeSupport);
+          this.handler, ContentType.JSON);
       handler.handleException(e, request, response);
-    }
+    }    
     convertToHttp(httpResponse, response);
   }
 

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7a68ae68/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ServiceDispatcher.java
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ServiceDispatcher.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ServiceDispatcher.java
index cb718e1..fc5c88c 100644
--- a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ServiceDispatcher.java
+++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ServiceDispatcher.java
@@ -23,16 +23,18 @@ import java.net.URI;
 import java.net.URISyntaxException;
 import java.net.URL;
 
+import org.apache.olingo.commons.api.ex.ODataException;
 import org.apache.olingo.commons.api.format.ContentType;
 import org.apache.olingo.commons.api.http.HttpHeader;
 import org.apache.olingo.commons.api.http.HttpStatusCode;
 import org.apache.olingo.server.api.OData;
 import org.apache.olingo.server.api.ODataApplicationException;
+import org.apache.olingo.server.api.ODataLibraryException;
 import org.apache.olingo.server.api.ODataRequest;
 import org.apache.olingo.server.api.ODataResponse;
-import org.apache.olingo.server.api.ODataLibraryException;
 import org.apache.olingo.server.api.ServiceMetadata;
 import org.apache.olingo.server.api.serializer.CustomContentTypeSupport;
+import org.apache.olingo.server.api.serializer.RepresentationType;
 import org.apache.olingo.server.api.uri.UriInfo;
 import org.apache.olingo.server.api.uri.UriInfoBatch;
 import org.apache.olingo.server.api.uri.UriInfoCrossjoin;
@@ -75,11 +77,36 @@ public class ServiceDispatcher extends RequestURLHierarchyVisitor {
     this.customContentSupport = customContentSupport;
   }
 
-  public void execute(ODataRequest odRequest, ODataResponse odResponse)
-      throws ODataLibraryException, ODataApplicationException {
-
-    UriInfo uriInfo = new Parser(this.metadata.getEdm(), odata)
-        .parseUri(odRequest.getRawODataPath(), odRequest.getRawQueryPath(), null);
+  public void execute(ODataRequest odRequest, ODataResponse odResponse) {
+    ContentType contentType = ContentType.JSON;
+    try {
+      contentType = ContentNegotiator.doContentNegotiation(null,
+          odRequest, this.customContentSupport, RepresentationType.ERROR);
+      
+      UriInfo uriInfo = new Parser(this.metadata.getEdm(), odata)
+      .parseUri(odRequest.getRawODataPath(), odRequest.getRawQueryPath(), null);
+      
+      contentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
+          odRequest, this.customContentSupport, RepresentationType.ERROR);      
+      
+      internalExecute(uriInfo, odRequest, odResponse);
+    } catch(ODataLibraryException e) {
+      handleException(e, contentType, odRequest, odResponse);
+    } catch(ODataApplicationException e) {
+      handleException(e, contentType, odRequest, odResponse);
+    }
+  }
+  
+  protected void handleException(ODataException e, ContentType contentType,
+      ODataRequest odRequest, ODataResponse odResponse) {
+    ErrorHandler handler = new ErrorHandler(this.odata, this.metadata,
+        this.handler, contentType);
+    handler.handleException(e, odRequest, odResponse);    
+  }
+  
+  private void internalExecute(UriInfo uriInfo, ODataRequest odRequest,
+      ODataResponse odResponse) throws ODataLibraryException,
+      ODataApplicationException {
 
     new UriValidator().validate(uriInfo, odRequest.getMethod());
 

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7a68ae68/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ServiceHandler.java
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ServiceHandler.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ServiceHandler.java
index ba96f94..8f8fc1d 100644
--- a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ServiceHandler.java
+++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ServiceHandler.java
@@ -26,9 +26,10 @@ import org.apache.olingo.commons.api.data.Entity;
 import org.apache.olingo.commons.api.data.Property;
 import org.apache.olingo.commons.api.http.HttpMethod;
 import org.apache.olingo.server.api.ODataApplicationException;
+import org.apache.olingo.server.api.ODataLibraryException;
 import org.apache.olingo.server.api.ODataRequest;
 import org.apache.olingo.server.api.ODataResponse;
-import org.apache.olingo.server.api.ODataLibraryException;
+import org.apache.olingo.server.api.ODataServerError;
 import org.apache.olingo.server.api.processor.Processor;
 import org.apache.olingo.server.core.requests.ActionRequest;
 import org.apache.olingo.server.core.requests.DataRequest;
@@ -37,6 +38,7 @@ import org.apache.olingo.server.core.requests.MediaRequest;
 import org.apache.olingo.server.core.requests.MetadataRequest;
 import org.apache.olingo.server.core.requests.ServiceDocumentRequest;
 import org.apache.olingo.server.core.responses.EntityResponse;
+import org.apache.olingo.server.core.responses.ErrorResponse;
 import org.apache.olingo.server.core.responses.MetadataResponse;
 import org.apache.olingo.server.core.responses.NoContentResponse;
 import org.apache.olingo.server.core.responses.PropertyResponse;
@@ -296,4 +298,13 @@ public interface ServiceHandler extends Processor {
    * @return
    */
   boolean supportsDataIsolation();
+  
+  
+  /**
+   * Handle errors generated by the framework as well as the service specific errors. This can be used
+   * one place handle error logging, error modification etc.   
+   * @param error 
+   * @param response
+   */
+  void processError(ODataServerError error, ErrorResponse response);
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7a68ae68/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/legacy/ProcessorServiceHandler.java
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/legacy/ProcessorServiceHandler.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/legacy/ProcessorServiceHandler.java
index db62c0a..d4d0662 100644
--- a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/legacy/ProcessorServiceHandler.java
+++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/legacy/ProcessorServiceHandler.java
@@ -32,6 +32,7 @@ import org.apache.olingo.server.api.ODataApplicationException;
 import org.apache.olingo.server.api.ODataRequest;
 import org.apache.olingo.server.api.ODataResponse;
 import org.apache.olingo.server.api.ODataLibraryException;
+import org.apache.olingo.server.api.ODataServerError;
 import org.apache.olingo.server.api.ServiceMetadata;
 import org.apache.olingo.server.api.processor.ComplexCollectionProcessor;
 import org.apache.olingo.server.api.processor.ComplexProcessor;
@@ -59,6 +60,7 @@ import org.apache.olingo.server.core.requests.ServiceDocumentRequest;
 import org.apache.olingo.server.core.responses.CountResponse;
 import org.apache.olingo.server.core.responses.EntityResponse;
 import org.apache.olingo.server.core.responses.EntitySetResponse;
+import org.apache.olingo.server.core.responses.ErrorResponse;
 import org.apache.olingo.server.core.responses.MetadataResponse;
 import org.apache.olingo.server.core.responses.NoContentResponse;
 import org.apache.olingo.server.core.responses.PrimitiveValueResponse;
@@ -442,4 +444,9 @@ public class ProcessorServiceHandler implements ServiceHandler {
   public boolean supportsDataIsolation() {
     return false;
   }
+
+  @Override
+  public void processError(ODataServerError error, ErrorResponse response) {
+    response.writeError(error);
+  }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7a68ae68/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/BatchRequest.java
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/BatchRequest.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/BatchRequest.java
index d14b5ad..2215594 100644
--- a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/BatchRequest.java
+++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/BatchRequest.java
@@ -29,16 +29,15 @@ import org.apache.olingo.commons.api.http.HttpHeader;
 import org.apache.olingo.commons.api.http.HttpStatusCode;
 import org.apache.olingo.server.api.OData;
 import org.apache.olingo.server.api.ODataApplicationException;
+import org.apache.olingo.server.api.ODataLibraryException;
 import org.apache.olingo.server.api.ODataRequest;
 import org.apache.olingo.server.api.ODataResponse;
-import org.apache.olingo.server.api.ODataLibraryException;
 import org.apache.olingo.server.api.ServiceMetadata;
 import org.apache.olingo.server.api.deserializer.batch.BatchDeserializerException;
 import org.apache.olingo.server.api.deserializer.batch.BatchOptions;
 import org.apache.olingo.server.api.deserializer.batch.BatchRequestPart;
 import org.apache.olingo.server.api.deserializer.batch.ODataResponsePart;
 import org.apache.olingo.server.core.ContentNegotiatorException;
-import org.apache.olingo.server.core.ErrorHandler;
 import org.apache.olingo.server.core.ServiceDispatcher;
 import org.apache.olingo.server.core.ServiceHandler;
 import org.apache.olingo.server.core.ServiceRequest;
@@ -154,13 +153,7 @@ public class BatchRequest extends ServiceRequest {
     ServiceDispatcher dispatcher = new ServiceDispatcher(this.odata, this.serviceMetadata, handler,
         this.customContentType);
     ODataResponse res = new ODataResponse();
-    try {
-      dispatcher.execute(singleRequest, res);
-    } catch (Exception e) {
-      ErrorHandler ehandler = new ErrorHandler(this.odata, this.serviceMetadata,
-          getCustomContentTypeSupport());
-      ehandler.handleException(e, singleRequest, res);
-    }
+    dispatcher.execute(singleRequest, res);
     return res;
   }
 

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7a68ae68/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/responses/EntityResponse.java
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/responses/EntityResponse.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/responses/EntityResponse.java
index a0bbd14..5f54a24 100644
--- a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/responses/EntityResponse.java
+++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/responses/EntityResponse.java
@@ -162,6 +162,7 @@ public class EntityResponse extends ServiceResponse {
   
   public void writeError(ODataServerError error) {
     try {
+      writeHeader(HttpHeader.CONTENT_TYPE, this.responseContentType.getType());
       writeContent(this.serializer.error(error).getContent(), error.getStatusCode(), true);
     } catch (SerializerException e) {
       writeServerError(true);

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7a68ae68/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/responses/EntitySetResponse.java
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/responses/EntitySetResponse.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/responses/EntitySetResponse.java
index 0dd2bd8..09a48c1 100644
--- a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/responses/EntitySetResponse.java
+++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/responses/EntitySetResponse.java
@@ -24,6 +24,7 @@ import org.apache.olingo.commons.api.data.ContextURL;
 import org.apache.olingo.commons.api.data.EntityCollection;
 import org.apache.olingo.commons.api.edm.EdmEntityType;
 import org.apache.olingo.commons.api.format.ContentType;
+import org.apache.olingo.commons.api.http.HttpHeader;
 import org.apache.olingo.server.api.ODataApplicationException;
 import org.apache.olingo.server.api.ODataResponse;
 import org.apache.olingo.server.api.ODataServerError;
@@ -84,6 +85,7 @@ public class EntitySetResponse extends ServiceResponse {
   
   public void writeError(ODataServerError error) {
     try {
+      writeHeader(HttpHeader.CONTENT_TYPE, this.responseContentType.getType());
       writeContent(this.serializer.error(error).getContent(), error.getStatusCode(), true);
     } catch (SerializerException e) {
       writeServerError(true);

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7a68ae68/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/responses/ErrorResponse.java
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/responses/ErrorResponse.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/responses/ErrorResponse.java
new file mode 100644
index 0000000..2e1fbd6
--- /dev/null
+++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/responses/ErrorResponse.java
@@ -0,0 +1,58 @@
+/*
+ * 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.server.core.responses;
+
+import java.util.HashMap;
+
+import org.apache.olingo.commons.api.format.ContentType;
+import org.apache.olingo.commons.api.http.HttpHeader;
+import org.apache.olingo.server.api.ODataApplicationException;
+import org.apache.olingo.server.api.ODataLibraryException;
+import org.apache.olingo.server.api.ODataResponse;
+import org.apache.olingo.server.api.ODataServerError;
+import org.apache.olingo.server.api.ServiceMetadata;
+import org.apache.olingo.server.api.serializer.ODataSerializer;
+import org.apache.olingo.server.api.serializer.SerializerException;
+
+public class ErrorResponse extends ServiceResponse {
+  private ContentType contentType;
+  private ODataSerializer serializer;
+  
+  public ErrorResponse(ServiceMetadata metadata, ODataSerializer serializer,
+      ContentType contentType, ODataResponse response) {
+    super(metadata, response, new HashMap<String, String>());
+    this.contentType = contentType;
+    this.serializer = serializer;
+  }
+
+  @Override
+  public void accepts(ServiceResponseVisior visitor)
+      throws ODataLibraryException, ODataApplicationException {
+    visitor.visit(this);
+  }
+
+  public void writeError(ODataServerError error) {
+    try {
+      writeHeader(HttpHeader.CONTENT_TYPE, this.contentType.getType());
+      writeContent(this.serializer.error(error).getContent(), error.getStatusCode(), true);
+    } catch (SerializerException e) {
+      writeServerError(true);
+    }
+  } 
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7a68ae68/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/responses/MetadataResponse.java
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/responses/MetadataResponse.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/responses/MetadataResponse.java
index 5facd96..c030336 100644
--- a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/responses/MetadataResponse.java
+++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/responses/MetadataResponse.java
@@ -21,6 +21,7 @@ package org.apache.olingo.server.core.responses;
 import java.util.Map;
 
 import org.apache.olingo.commons.api.format.ContentType;
+import org.apache.olingo.commons.api.http.HttpHeader;
 import org.apache.olingo.server.api.ODataApplicationException;
 import org.apache.olingo.server.api.ODataResponse;
 import org.apache.olingo.server.api.ODataServerError;
@@ -63,6 +64,7 @@ public class MetadataResponse extends ServiceResponse {
   
   public void writeError(ODataServerError error) {
     try {
+      writeHeader(HttpHeader.CONTENT_TYPE, this.responseContentType.getType());
       writeContent(this.serializer.error(error).getContent(), error.getStatusCode(), true);
     } catch (SerializerException e) {
       writeServerError(true);

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7a68ae68/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/responses/PropertyResponse.java
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/responses/PropertyResponse.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/responses/PropertyResponse.java
index 1fc5416..f9c35ba 100644
--- a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/responses/PropertyResponse.java
+++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/responses/PropertyResponse.java
@@ -27,6 +27,7 @@ import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
 import org.apache.olingo.commons.api.edm.EdmType;
 import org.apache.olingo.commons.api.edm.constants.EdmTypeKind;
 import org.apache.olingo.commons.api.format.ContentType;
+import org.apache.olingo.commons.api.http.HttpHeader;
 import org.apache.olingo.commons.api.http.HttpStatusCode;
 import org.apache.olingo.server.api.ODataApplicationException;
 import org.apache.olingo.server.api.ODataResponse;
@@ -148,6 +149,7 @@ public class PropertyResponse extends ServiceResponse {
   
   public void writeError(ODataServerError error) {
     try {
+      writeHeader(HttpHeader.CONTENT_TYPE, this.responseContentType.getType());
       writeContent(this.serializer.error(error).getContent(), error.getStatusCode(), true);
     } catch (SerializerException e) {
       writeServerError(true);

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7a68ae68/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/responses/ServiceDocumentResponse.java
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/responses/ServiceDocumentResponse.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/responses/ServiceDocumentResponse.java
index 0d7a88c..a4192e7 100644
--- a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/responses/ServiceDocumentResponse.java
+++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/responses/ServiceDocumentResponse.java
@@ -21,6 +21,7 @@ package org.apache.olingo.server.core.responses;
 import java.util.Map;
 
 import org.apache.olingo.commons.api.format.ContentType;
+import org.apache.olingo.commons.api.http.HttpHeader;
 import org.apache.olingo.server.api.ODataApplicationException;
 import org.apache.olingo.server.api.ODataResponse;
 import org.apache.olingo.server.api.ODataServerError;
@@ -64,6 +65,7 @@ public class ServiceDocumentResponse extends ServiceResponse {
   
   public void writeError(ODataServerError error) {
     try {
+      writeHeader(HttpHeader.CONTENT_TYPE, this.responseContentType.getType());
       writeContent(this.serializer.error(error).getContent(), error.getStatusCode(), true);
     } catch (SerializerException e) {
       writeServerError(true);

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7a68ae68/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/responses/ServiceResponseVisior.java
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/responses/ServiceResponseVisior.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/responses/ServiceResponseVisior.java
index 5be8113..fb73b8c 100644
--- a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/responses/ServiceResponseVisior.java
+++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/responses/ServiceResponseVisior.java
@@ -67,4 +67,8 @@ public class ServiceResponseVisior {
       ODataApplicationException {
     response.writeServerError(true);
   }
+
+  public void visit(ErrorResponse response) {
+    response.writeServerError(true);
+  }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7a68ae68/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinHandler.java
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinHandler.java b/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinHandler.java
index fea02e9..4d2dbb9 100644
--- a/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinHandler.java
+++ b/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinHandler.java
@@ -40,9 +40,10 @@ import org.apache.olingo.commons.api.format.ContentType;
 import org.apache.olingo.commons.api.http.HttpMethod;
 import org.apache.olingo.server.api.OData;
 import org.apache.olingo.server.api.ODataApplicationException;
+import org.apache.olingo.server.api.ODataLibraryException;
 import org.apache.olingo.server.api.ODataRequest;
 import org.apache.olingo.server.api.ODataResponse;
-import org.apache.olingo.server.api.ODataLibraryException;
+import org.apache.olingo.server.api.ODataServerError;
 import org.apache.olingo.server.api.ServiceMetadata;
 import org.apache.olingo.server.api.uri.UriParameter;
 import org.apache.olingo.server.api.uri.UriResourceNavigation;
@@ -56,6 +57,7 @@ import org.apache.olingo.server.core.requests.ServiceDocumentRequest;
 import org.apache.olingo.server.core.responses.CountResponse;
 import org.apache.olingo.server.core.responses.EntityResponse;
 import org.apache.olingo.server.core.responses.EntitySetResponse;
+import org.apache.olingo.server.core.responses.ErrorResponse;
 import org.apache.olingo.server.core.responses.MetadataResponse;
 import org.apache.olingo.server.core.responses.NoContentResponse;
 import org.apache.olingo.server.core.responses.PrimitiveValueResponse;
@@ -561,4 +563,9 @@ public class TripPinHandler implements ServiceHandler {
   public boolean supportsDataIsolation() {
     return false;
   }
+  
+  @Override
+  public void processError(ODataServerError error, ErrorResponse response) {
+    response.writeError(error);
+  }
 }


[14/22] olingo-odata4 git commit: Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/olingo-odata4

Posted by mi...@apache.org.
Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/olingo-odata4


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

Branch: refs/heads/OLINGO-832_StreamSerializerPoC
Commit: 280bc019cebd8d05f7f27ecd2b069e3eb5300a69
Parents: 6d94f0e 53065cd
Author: Ramesh Reddy <ra...@jboss.org>
Authored: Sat Feb 6 13:32:04 2016 -0600
Committer: Ramesh Reddy <ra...@jboss.org>
Committed: Sat Feb 6 13:32:04 2016 -0600

----------------------------------------------------------------------
 .../commons/AbstractInvocationHandler.java      |   17 +-
 .../AbstractStructuredInvocationHandler.java    |    2 +-
 .../commons/AnnotatationsInvocationHandler.java |    2 +-
 .../ComplexCollectionInvocationHandler.java     |    2 +-
 .../proxy/commons/ComplexInvocationHandler.java |    6 +-
 .../proxy/commons/EdmStreamValueHandler.java    |    2 +-
 .../EntityCollectionInvocationHandler.java      |    2 +-
 .../EntityContainerInvocationHandler.java       |    4 +-
 .../proxy/commons/EntityInvocationHandler.java  |    6 +-
 .../commons/EntitySetInvocationHandler.java     |    2 +-
 .../proxy/commons/InvokerInvocationHandler.java |    2 +-
 .../commons/OperationInvocationHandler.java     |    2 +-
 .../PrimitiveCollectionInvocationHandler.java   |    2 +-
 ...turedComposableInvokerInvocationHandler.java |    2 +-
 .../olingo/ext/proxy/utils/CoreUtils.java       |    5 +-
 .../org/apache/olingo/fit/AbstractServices.java | 1947 --------------
 .../main/java/org/apache/olingo/fit/Demo.java   |    6 +-
 .../java/org/apache/olingo/fit/OpenType.java    |    5 +-
 .../java/org/apache/olingo/fit/Services.java    | 2511 +++++++++++++++---
 .../org/apache/olingo/fit/Vocabularies.java     |   10 +-
 .../apache/olingo/fit/metadata/EntitySet.java   |    8 -
 .../olingo/fit/rest/OAuth2RequestFilter.java    |    3 +-
 .../fit/serializer/FITAtomDeserializer.java     |   13 +-
 .../olingo/fit/utils/AbstractUtilities.java     |   22 +-
 .../org/apache/olingo/fit/utils/Accept.java     |   31 +-
 .../org/apache/olingo/fit/utils/Commons.java    |   24 +-
 .../apache/olingo/fit/utils/ConstantKey.java    |   10 +-
 .../org/apache/olingo/fit/utils/Constants.java  |    7 -
 .../org/apache/olingo/fit/utils/FSManager.java  |   25 +-
 .../fit/utils/InjectableSerializerProvider.java |   42 -
 .../apache/olingo/fit/utils/JSONUtilities.java  |   14 +-
 .../olingo/fit/utils/MetadataLinkInfo.java      |  182 --
 .../apache/olingo/fit/utils/XMLUtilities.java   |    3 +
 .../proxy/demo/odatademo/types/Customer.java    |    6 +-
 .../proxy/demo/odatademo/types/Employee.java    |    6 +-
 .../demo/odatademo/types/FeaturedProduct.java   |    6 +-
 .../opentypesservice/types/IndexedRow.java      |    8 +-
 .../odatawcfservice/types/CreditCardPI.java     |    6 +-
 .../odatawcfservice/types/Customer.java         |    6 +-
 .../odatawcfservice/types/Employee.java         |    6 +-
 .../odatawcfservice/types/PublicCompany.java    |    8 +-
 .../tecsvc/client/EntityReferencesITCase.java   |   13 +-
 .../ExpandWithSystemQueryOptionsITCase.java     |   74 +-
 .../core/domain/AbstractClientEntitySet.java    |  114 -
 .../core/domain/ClientCollectionValueImpl.java  |    2 +-
 .../client/core/domain/ClientEntitySetImpl.java |   74 +-
 .../core/domain/ClientPrimitiveValueImpl.java   |    5 +-
 .../client/core/domain/ClientPropertyImpl.java  |  135 +-
 .../client/core/domain/ClientValuableImpl.java  |   22 +-
 .../core/serialization/ODataBinderImpl.java     |    2 +-
 .../apache/olingo/client/core/AbstractTest.java |    9 +-
 .../org/apache/olingo/client/core/AtomTest.java |    6 -
 .../olingo/client/core/EntitySetTest.java       |   22 +-
 .../apache/olingo/client/core/EntityTest.java   |   73 +-
 .../apache/olingo/client/core/ErrorTest.java    |    8 +-
 .../org/apache/olingo/client/core/JSONTest.java |   46 +-
 .../apache/olingo/client/core/MetadataTest.java |   33 +-
 .../olingo/client/core/PrimitiveValueTest.java  |   22 +-
 .../apache/olingo/client/core/PropertyTest.java |   38 +-
 .../olingo/client/core/ServiceDocumentTest.java |   16 +-
 .../client/core/uri/FilterFactoryTest.java      |    8 +-
 .../olingo/client/core/uri/URIBuilderTest.java  |   71 +-
 .../olingo/commons/api/edm/geo/Geospatial.java  |    7 +-
 .../commons/core/edm/EdmEntityTypeImpl.java     |    7 +-
 .../core/edm/EdmNavigationPropertyImpl.java     |    3 +-
 .../commons/core/edm/EdmParameterImpl.java      |    3 +-
 .../commons/core/edm/EdmPropertyImpl.java       |    5 +-
 .../edm/provider/EdmEntityTypeImplTest.java     |   19 +
 .../uri/queryoption/SystemQueryOptionKind.java  |   22 +-
 .../apache/olingo/server/core/ODataHandler.java |    4 +-
 .../server/core/ODataHttpHandlerImpl.java       |   19 +-
 .../core/batchhandler/BatchFacadeImpl.java      |   18 +-
 .../server/core/batchhandler/BatchHandler.java  |    2 +-
 .../olingo/server/core/uri/UriInfoImpl.java     |   37 +-
 .../server/core/uri/parser/ExpandParser.java    |   30 +-
 .../core/uri/parser/ExpressionParser.java       |   85 +-
 .../server/core/uri/parser/FilterParser.java    |    6 +-
 .../server/core/uri/parser/OrderByParser.java   |    6 +-
 .../olingo/server/core/uri/parser/Parser.java   |  354 +--
 .../server/core/uri/parser/ParserHelper.java    |  168 +-
 .../core/uri/parser/ResourcePathParser.java     |   38 +-
 .../server/core/uri/parser/SelectParser.java    |   12 +-
 .../server/core/uri/parser/UriTokenizer.java    |   12 +-
 .../uri/queryoption/expression/AliasImpl.java   |    9 +-
 .../uri/validator/UriValidationException.java   |    4 +-
 .../server/core/uri/validator/UriValidator.java |  513 +---
 .../server-core-exceptions-i18n.properties      |    1 +
 .../olingo/server/core/uri/UriInfoImplTest.java |   50 +-
 .../core/uri/parser/ExpressionParserTest.java   |    2 +-
 .../core/uri/parser/UriTokenizerTest.java       |    3 +
 .../olingo/server/tecsvc/data/DataProvider.java |   12 +-
 .../SystemQueryOptionsRuntimeException.java     |    3 +-
 .../tecsvc/provider/ContainerProvider.java      |    6 +-
 .../core/uri/parser/TestFullResourcePath.java   |  112 +-
 .../core/uri/queryoption/QueryOptionTest.java   |    4 +-
 .../queryoption/expression/ExpressionTest.java  |    6 +-
 .../core/uri/testutil/FilterValidator.java      |   51 +-
 .../core/uri/validator/UriValidatorTest.java    |   68 +-
 98 files changed, 3310 insertions(+), 4157 deletions(-)
----------------------------------------------------------------------



[06/22] olingo-odata4 git commit: [OLINGO-852] less warnings + general clean-up

Posted by mi...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/lib/client-core/src/test/java/org/apache/olingo/client/core/EntityTest.java
----------------------------------------------------------------------
diff --git a/lib/client-core/src/test/java/org/apache/olingo/client/core/EntityTest.java b/lib/client-core/src/test/java/org/apache/olingo/client/core/EntityTest.java
index 9f5d405..0d075a9 100644
--- a/lib/client-core/src/test/java/org/apache/olingo/client/core/EntityTest.java
+++ b/lib/client-core/src/test/java/org/apache/olingo/client/core/EntityTest.java
@@ -50,11 +50,6 @@ import org.junit.Test;
 
 public class EntityTest extends AbstractTest {
 
-  @Override
-  protected ODataClient getClient() {
-    return v4Client;
-  }
-
   private EdmEnabledODataClient getEdmEnabledClient() {
     return new EdmEnabledODataClientImpl(null, null, null) {
 
@@ -78,8 +73,8 @@ public class EntityTest extends AbstractTest {
 
   private void singleton(final ContentType contentType) throws Exception {
     final InputStream input = getClass().getResourceAsStream("VipCustomer." + getSuffix(contentType));
-    final ClientEntity entity = getClient().getBinder().getODataEntity(
-        getClient().getDeserializer(contentType).toEntity(input));
+    final ClientEntity entity = client.getBinder().getODataEntity(
+        client.getDeserializer(contentType).toEntity(input));
     assertNotNull(entity);
 
     assertEquals("Microsoft.Test.OData.Services.ODataWCFService.Customer", entity.getTypeName().toString());
@@ -120,8 +115,8 @@ public class EntityTest extends AbstractTest {
 
     // operations won't get serialized
     entity.getOperations().clear();
-    final ClientEntity written = getClient().getBinder().getODataEntity(
-        new ResWrap<Entity>((URI) null, null, getClient().getBinder().getEntity(entity)));
+    final ClientEntity written = client.getBinder().getODataEntity(
+        new ResWrap<Entity>((URI) null, null, client.getBinder().getEntity(entity)));
     assertEquals(entity, written);
     input.close();
   }
@@ -138,8 +133,8 @@ public class EntityTest extends AbstractTest {
 
   private void withEnums(final ContentType contentType) throws Exception {
     final InputStream input = getClass().getResourceAsStream("Products_5." + getSuffix(contentType));
-    final ClientEntity entity = getClient().getBinder().getODataEntity(
-        getClient().getDeserializer(contentType).toEntity(input));
+    final ClientEntity entity = client.getBinder().getODataEntity(
+        client.getDeserializer(contentType).toEntity(input));
     assertNotNull(entity);
 
     final ClientProperty skinColor = entity.getProperty("SkinColor");
@@ -156,8 +151,8 @@ public class EntityTest extends AbstractTest {
 
     // operations won't get serialized
     entity.getOperations().clear();
-    final ClientEntity written = getClient().getBinder().getODataEntity(
-        new ResWrap<Entity>((URI) null, null, getClient().getBinder().getEntity(entity)));
+    final ClientEntity written = client.getBinder().getODataEntity(
+        new ResWrap<Entity>((URI) null, null, client.getBinder().getEntity(entity)));
     assertEquals(entity, written);
     input.close();
   }
@@ -175,8 +170,8 @@ public class EntityTest extends AbstractTest {
   private void withInlineEntitySet(final ContentType contentType) throws Exception {
     final InputStream input = getClass().getResourceAsStream(
         "Accounts_101_expand_MyPaymentInstruments." + getSuffix(contentType));
-    final ClientEntity entity = getClient().getBinder().getODataEntity(
-        getClient().getDeserializer(contentType).toEntity(input));
+    final ClientEntity entity = client.getBinder().getODataEntity(
+        client.getDeserializer(contentType).toEntity(input));
     assertNotNull(entity);
 
     final ClientLink instruments = entity.getNavigationLink("MyPaymentInstruments");
@@ -191,8 +186,8 @@ public class EntityTest extends AbstractTest {
     inline.getEntitySet().setCount(3);
     // operations won't get serialized
     entity.getOperations().clear();
-    final ClientEntity written = getClient().getBinder().getODataEntity(
-        new ResWrap<Entity>((URI) null, null, getClient().getBinder().getEntity(entity)));
+    final ClientEntity written = client.getBinder().getODataEntity(
+        new ResWrap<Entity>((URI) null, null, client.getBinder().getEntity(entity)));
     assertEquals(entity, written);
     input.close();
   }
@@ -210,16 +205,16 @@ public class EntityTest extends AbstractTest {
   private void mediaEntity(final ContentType contentType) throws Exception {
     final InputStream input = getClass().getResourceAsStream(
         "Advertisements_f89dee73-af9f-4cd4-b330-db93c25ff3c7." + getSuffix(contentType));
-    final ClientEntity entity = getClient().getBinder().getODataEntity(
-        getClient().getDeserializer(contentType).toEntity(input));
+    final ClientEntity entity = client.getBinder().getODataEntity(
+        client.getDeserializer(contentType).toEntity(input));
     assertNotNull(entity);
 
     assertTrue(entity.isMediaEntity());
     assertNotNull(entity.getMediaContentSource());
     assertEquals("\"8zOOKKvgOtptr4gt8IrnapX3jds=\"", entity.getMediaETag());
 
-    final ClientEntity written = getClient().getBinder().getODataEntity(
-        new ResWrap<Entity>((URI) null, null, getClient().getBinder().getEntity(entity)));
+    final ClientEntity written = client.getBinder().getODataEntity(
+        new ResWrap<Entity>((URI) null, null, client.getBinder().getEntity(entity)));
     assertEquals(entity, written);
     input.close();
   }
@@ -236,8 +231,8 @@ public class EntityTest extends AbstractTest {
 
   private void withStream(final ContentType contentType) throws Exception {
     final InputStream input = getClass().getResourceAsStream("PersonDetails_1." + getSuffix(contentType));
-    final ClientEntity entity = getClient().getBinder().getODataEntity(
-        getClient().getDeserializer(contentType).toEntity(input));
+    final ClientEntity entity = client.getBinder().getODataEntity(
+        client.getDeserializer(contentType).toEntity(input));
     assertNotNull(entity);
 
     assertFalse(entity.isMediaEntity());
@@ -245,8 +240,8 @@ public class EntityTest extends AbstractTest {
     final ClientLink editMedia = entity.getMediaEditLink("Photo");
     assertNotNull(editMedia);
 
-    final ClientEntity written = getClient().getBinder().getODataEntity(
-        new ResWrap<Entity>((URI) null, null, getClient().getBinder().getEntity(entity)));
+    final ClientEntity written = client.getBinder().getODataEntity(
+        new ResWrap<Entity>((URI) null, null, client.getBinder().getEntity(entity)));
     assertEquals(entity, written);
     input.close();
   }
@@ -263,14 +258,14 @@ public class EntityTest extends AbstractTest {
 
   private void ref(final ContentType contentType) throws Exception {
     final InputStream input = getClass().getResourceAsStream("entityReference." + getSuffix(contentType));
-    final ClientEntity entity = getClient().getBinder().getODataEntity(
-        getClient().getDeserializer(contentType).toEntity(input));
+    final ClientEntity entity = client.getBinder().getODataEntity(
+        client.getDeserializer(contentType).toEntity(input));
     assertNotNull(entity);
 
     assertNotNull(entity.getId());
 
-    final ClientEntity written = getClient().getBinder().getODataEntity(
-        new ResWrap<Entity>((URI) null, null, getClient().getBinder().getEntity(entity)));
+    final ClientEntity written = client.getBinder().getODataEntity(
+        new ResWrap<Entity>((URI) null, null, client.getBinder().getEntity(entity)));
     assertEquals(entity, written);
     input.close();
   }
@@ -287,8 +282,8 @@ public class EntityTest extends AbstractTest {
 
   private void complexNavigationProperties(final ContentType contentType) throws Exception {
     final InputStream input = getClass().getResourceAsStream("entity.withcomplexnavigation." + getSuffix(contentType));
-    final ClientEntity entity = getClient().getBinder().getODataEntity(
-        getClient().getDeserializer(contentType).toEntity(input));
+    final ClientEntity entity = client.getBinder().getODataEntity(
+        client.getDeserializer(contentType).toEntity(input));
     assertNotNull(entity);
 
     final ClientComplexValue addressValue = entity.getProperty("Address").getComplexValue();
@@ -297,8 +292,8 @@ public class EntityTest extends AbstractTest {
 
     // ETag is not serialized
     entity.setETag(null);
-    final ClientEntity written = getClient().getBinder().getODataEntity(
-        new ResWrap<Entity>((URI) null, null, getClient().getBinder().getEntity(entity)));
+    final ClientEntity written = client.getBinder().getODataEntity(
+        new ResWrap<Entity>((URI) null, null, client.getBinder().getEntity(entity)));
     assertEquals(entity, written);
     input.close();
   }
@@ -315,8 +310,8 @@ public class EntityTest extends AbstractTest {
 
   private void annotated(final ContentType contentType) throws EdmPrimitiveTypeException, Exception {
     final InputStream input = getClass().getResourceAsStream("annotated." + getSuffix(contentType));
-    final ClientEntity entity = getClient().getBinder().getODataEntity(
-        getClient().getDeserializer(contentType).toEntity(input));
+    final ClientEntity entity = client.getBinder().getODataEntity(
+        client.getDeserializer(contentType).toEntity(input));
     assertNotNull(entity);
 
     assertFalse(entity.getAnnotations().isEmpty());
@@ -343,8 +338,8 @@ public class EntityTest extends AbstractTest {
     assertEquals(2,
         annotation.getValue().asComplex().get("order").getPrimitiveValue().toCastValue(Integer.class), 0);
 
-    final ClientEntity written = getClient().getBinder().getODataEntity(
-        new ResWrap<Entity>((URI) null, null, getClient().getBinder().getEntity(entity)));
+    final ClientEntity written = client.getBinder().getODataEntity(
+        new ResWrap<Entity>((URI) null, null, client.getBinder().getEntity(entity)));
     assertEquals(entity, written);
     input.close();
   }
@@ -374,7 +369,7 @@ public class EntityTest extends AbstractTest {
 
   @Test
   public void derivedFromAtom() throws Exception {
-    derived(getClient(), ContentType.APPLICATION_ATOM_XML);
+    derived(client, ContentType.APPLICATION_ATOM_XML);
   }
 
   @Test
@@ -384,6 +379,6 @@ public class EntityTest extends AbstractTest {
 
   @Test
   public void derivedFromFullJSON() throws Exception {
-    derived(getClient(), ContentType.JSON_FULL_METADATA);
+    derived(client, ContentType.JSON_FULL_METADATA);
   }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/lib/client-core/src/test/java/org/apache/olingo/client/core/ErrorTest.java
----------------------------------------------------------------------
diff --git a/lib/client-core/src/test/java/org/apache/olingo/client/core/ErrorTest.java b/lib/client-core/src/test/java/org/apache/olingo/client/core/ErrorTest.java
index 8ced6a3..60bbcd0 100644
--- a/lib/client-core/src/test/java/org/apache/olingo/client/core/ErrorTest.java
+++ b/lib/client-core/src/test/java/org/apache/olingo/client/core/ErrorTest.java
@@ -21,7 +21,6 @@ package org.apache.olingo.client.core;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 
-import org.apache.olingo.client.api.ODataClient;
 import org.apache.olingo.client.api.serialization.ODataDeserializerException;
 import org.apache.olingo.commons.api.ex.ODataError;
 import org.apache.olingo.commons.api.format.ContentType;
@@ -29,13 +28,8 @@ import org.junit.Test;
 
 public class ErrorTest extends AbstractTest {
 
-  @Override
-  protected ODataClient getClient() {
-    return v4Client;
-  }
-
   private ODataError error(final String name, final ContentType contentType) throws ODataDeserializerException {
-    final ODataError error = getClient().getDeserializer(contentType).toError(
+    final ODataError error = client.getDeserializer(contentType).toError(
             getClass().getResourceAsStream(name + "." + getSuffix(contentType)));
     assertNotNull(error);
     return error;

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/lib/client-core/src/test/java/org/apache/olingo/client/core/JSONTest.java
----------------------------------------------------------------------
diff --git a/lib/client-core/src/test/java/org/apache/olingo/client/core/JSONTest.java b/lib/client-core/src/test/java/org/apache/olingo/client/core/JSONTest.java
index 9273229..a276c4f 100644
--- a/lib/client-core/src/test/java/org/apache/olingo/client/core/JSONTest.java
+++ b/lib/client-core/src/test/java/org/apache/olingo/client/core/JSONTest.java
@@ -30,7 +30,6 @@ import java.util.List;
 import java.util.Map;
 
 import org.apache.commons.io.IOUtils;
-import org.apache.olingo.client.api.ODataClient;
 import org.apache.olingo.client.api.domain.ClientCollectionValue;
 import org.apache.olingo.client.api.domain.ClientComplexValue;
 import org.apache.olingo.client.api.domain.ClientEntity;
@@ -50,11 +49,6 @@ public class JSONTest extends AbstractTest {
 
   private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
 
-  @Override
-  protected ODataClient getClient() {
-    return v4Client;
-  }
-
   protected ContentType getODataPubFormat() {
     return ContentType.JSON;
   }
@@ -129,7 +123,7 @@ public class JSONTest extends AbstractTest {
 
   protected void entitySet(final String filename, final ContentType contentType) throws Exception {
     final StringWriter writer = new StringWriter();
-    getClient().getSerializer(contentType).write(writer, getClient().getDeserializer(contentType).toEntitySet(
+    client.getSerializer(contentType).write(writer, client.getDeserializer(contentType).toEntitySet(
         getClass().getResourceAsStream(filename + "." + getSuffix(contentType))).getPayload());
 
     assertSimilar(filename + "." + getSuffix(contentType), writer.toString());
@@ -143,7 +137,7 @@ public class JSONTest extends AbstractTest {
 
   protected void entity(final String filename, final ContentType contentType) throws Exception {
     final StringWriter writer = new StringWriter();
-    getClient().getSerializer(contentType).write(writer, getClient().getDeserializer(contentType).toEntity(
+    client.getSerializer(contentType).write(writer, client.getDeserializer(contentType).toEntity(
         getClass().getResourceAsStream(filename + "." + getSuffix(contentType))).getPayload());
     assertSimilar(filename + "." + getSuffix(contentType), writer.toString());
   }
@@ -169,7 +163,7 @@ public class JSONTest extends AbstractTest {
 
   protected void property(final String filename, final ContentType contentType) throws Exception {
     final StringWriter writer = new StringWriter();
-    getClient().getSerializer(contentType).write(writer, getClient().getDeserializer(contentType).
+    client.getSerializer(contentType).write(writer, client.getDeserializer(contentType).
         toProperty(getClass().getResourceAsStream(filename + "." + getSuffix(contentType))).getPayload());
 
     assertSimilar(filename + "." + getSuffix(contentType), writer.toString());
@@ -185,12 +179,12 @@ public class JSONTest extends AbstractTest {
 
   @Test
   public void crossjoin() throws Exception {
-    assertNotNull(getClient().getDeserializer(ContentType.JSON_FULL_METADATA).toEntitySet(
+    assertNotNull(client.getDeserializer(ContentType.JSON_FULL_METADATA).toEntitySet(
         getClass().getResourceAsStream("crossjoin.json")));
   }
 
   protected void delta(final String filename, final ContentType contentType) throws Exception {
-    final Delta delta = getClient().getDeserializer(contentType).toDelta(
+    final Delta delta = client.getDeserializer(contentType).toDelta(
         getClass().getResourceAsStream(filename + "." + getSuffix(contentType))).getPayload();
     assertNotNull(delta);
     assertNotNull(delta.getDeltaLink());
@@ -223,30 +217,30 @@ public class JSONTest extends AbstractTest {
 
   @Test
   public void issueOLINGO390() throws Exception {
-    final ClientEntity message = getClient().getObjectFactory().
+    final ClientEntity message = client.getObjectFactory().
         newEntity(new FullQualifiedName("Microsoft.Exchange.Services.OData.Model.Message"));
 
-    final ClientComplexValue toRecipient = getClient().getObjectFactory().
+    final ClientComplexValue toRecipient = client.getObjectFactory().
         newComplexValue("Microsoft.Exchange.Services.OData.Model.Recipient");
-    toRecipient.add(getClient().getObjectFactory().newPrimitiveProperty("Name",
-        getClient().getObjectFactory().newPrimitiveValueBuilder().buildString("challen_olingo_client")));
-    toRecipient.add(getClient().getObjectFactory().newPrimitiveProperty("Address",
-        getClient().getObjectFactory().newPrimitiveValueBuilder().buildString("challenh@microsoft.com")));
-    final ClientCollectionValue<ClientValue> toRecipients = getClient().getObjectFactory().
+    toRecipient.add(client.getObjectFactory().newPrimitiveProperty("Name",
+        client.getObjectFactory().newPrimitiveValueBuilder().buildString("challen_olingo_client")));
+    toRecipient.add(client.getObjectFactory().newPrimitiveProperty("Address",
+        client.getObjectFactory().newPrimitiveValueBuilder().buildString("challenh@microsoft.com")));
+    final ClientCollectionValue<ClientValue> toRecipients = client.getObjectFactory().
         newCollectionValue("Microsoft.Exchange.Services.OData.Model.Recipient");
     toRecipients.add(toRecipient);
-    message.getProperties().add(getClient().getObjectFactory().newCollectionProperty("ToRecipients", toRecipients));
+    message.getProperties().add(client.getObjectFactory().newCollectionProperty("ToRecipients", toRecipients));
 
     final ClientComplexValue body =
-        getClient().getObjectFactory().newComplexValue("Microsoft.Exchange.Services.OData.Model.ItemBody");
-    body.add(getClient().getObjectFactory().newPrimitiveProperty("Content",
-        getClient().getObjectFactory().newPrimitiveValueBuilder().
+        client.getObjectFactory().newComplexValue("Microsoft.Exchange.Services.OData.Model.ItemBody");
+    body.add(client.getObjectFactory().newPrimitiveProperty("Content",
+        client.getObjectFactory().newPrimitiveValueBuilder().
             buildString("this is a simple email body content")));
-    body.add(getClient().getObjectFactory().newEnumProperty("ContentType",
-        getClient().getObjectFactory().newEnumValue("Microsoft.Exchange.Services.OData.Model.BodyType", "text")));
-    message.getProperties().add(getClient().getObjectFactory().newComplexProperty("Body", body));
+    body.add(client.getObjectFactory().newEnumProperty("ContentType",
+        client.getObjectFactory().newEnumValue("Microsoft.Exchange.Services.OData.Model.BodyType", "text")));
+    message.getProperties().add(client.getObjectFactory().newComplexProperty("Body", body));
 
-    final String actual = IOUtils.toString(getClient().getWriter().writeEntity(message, ContentType.JSON));
+    final String actual = IOUtils.toString(client.getWriter().writeEntity(message, ContentType.JSON));
     final JsonNode expected =
         OBJECT_MAPPER.readTree(IOUtils.toString(getClass().getResourceAsStream("olingo390.json")).
             replace(Constants.JSON_NAVIGATION_LINK, Constants.JSON_BIND_LINK_SUFFIX));

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/lib/client-core/src/test/java/org/apache/olingo/client/core/MetadataTest.java
----------------------------------------------------------------------
diff --git a/lib/client-core/src/test/java/org/apache/olingo/client/core/MetadataTest.java b/lib/client-core/src/test/java/org/apache/olingo/client/core/MetadataTest.java
index a24ca36..c150e64 100644
--- a/lib/client-core/src/test/java/org/apache/olingo/client/core/MetadataTest.java
+++ b/lib/client-core/src/test/java/org/apache/olingo/client/core/MetadataTest.java
@@ -26,7 +26,6 @@ import static org.junit.Assert.assertTrue;
 import java.io.InputStream;
 import java.util.List;
 
-import org.apache.olingo.client.api.ODataClient;
 import org.apache.olingo.client.api.edm.xml.XMLMetadata;
 import org.apache.olingo.commons.api.Constants;
 import org.apache.olingo.commons.api.edm.Edm;
@@ -72,14 +71,9 @@ import org.junit.Test;
 
 public class MetadataTest extends AbstractTest {
 
-  @Override
-  protected ODataClient getClient() {
-    return v4Client;
-  }
-
   @Test
   public void parse() {
-    final Edm edm = getClient().getReader().readMetadata(getClass().getResourceAsStream("metadata.xml"));
+    final Edm edm = client.getReader().readMetadata(getClass().getResourceAsStream("metadata.xml"));
     assertNotNull(edm);
 
     // 1. Enum
@@ -140,7 +134,7 @@ public class MetadataTest extends AbstractTest {
 
   @Test
   public void demo() {
-    final XMLMetadata metadata = getClient().getDeserializer(ContentType.APPLICATION_XML).
+    final XMLMetadata metadata = client.getDeserializer(ContentType.APPLICATION_XML).
         toMetadata(getClass().getResourceAsStream("demo-metadata.xml"));
     assertNotNull(metadata);
 
@@ -154,7 +148,7 @@ public class MetadataTest extends AbstractTest {
         annots.getAnnotation("Org.OData.Publication.V1.PrivacyPolicyUrl").getExpression().asConstant().getValue());
 
     // Now let's test some edm:Annotations
-    final Edm edm = getClient().getReader().
+    final Edm edm = client.getReader().
         readMetadata(getClass().getResourceAsStream("demo-metadata.xml"));
     assertNotNull(edm);
 
@@ -181,7 +175,7 @@ public class MetadataTest extends AbstractTest {
 
   @Test
   public void multipleSchemas() {
-    final XMLMetadata metadata = getClient().getDeserializer(ContentType.APPLICATION_XML).
+    final XMLMetadata metadata = client.getDeserializer(ContentType.APPLICATION_XML).
         toMetadata(getClass().getResourceAsStream("northwind-metadata.xml"));
     assertNotNull(metadata);
 
@@ -198,10 +192,10 @@ public class MetadataTest extends AbstractTest {
 
   @Test
   public void getContainerWithoutCallingGetSchemas() {
-    final XMLMetadata metadata = getClient().getDeserializer(ContentType.APPLICATION_XML).
+    final XMLMetadata metadata = client.getDeserializer(ContentType.APPLICATION_XML).
         toMetadata(getClass().getResourceAsStream("fromdoc1-metadata.xml"));
 
-    Edm edm = getClient().getReader().readMetadata(metadata.getSchemaByNsOrAlias());
+    Edm edm = client.getReader().readMetadata(metadata.getSchemaByNsOrAlias());
 
     assertNotNull(edm.getEntityContainer());
   }
@@ -211,7 +205,7 @@ public class MetadataTest extends AbstractTest {
    */
   @Test
   public void fromdoc1() {
-    final XMLMetadata metadata = getClient().getDeserializer(ContentType.APPLICATION_XML).
+    final XMLMetadata metadata = client.getDeserializer(ContentType.APPLICATION_XML).
         toMetadata(getClass().getResourceAsStream("fromdoc1-metadata.xml"));
     assertNotNull(metadata);
 
@@ -249,7 +243,7 @@ public class MetadataTest extends AbstractTest {
         functionImport.getFunction());
 
     // Now let's go high-level
-    final Edm edm = getClient().getReader().readMetadata(getClass().getResourceAsStream("fromdoc1-metadata.xml"));
+    final Edm edm = client.getReader().readMetadata(getClass().getResourceAsStream("fromdoc1-metadata.xml"));
     assertNotNull(edm);
 
     List<EdmSchema> schemaList = edm.getSchemas();
@@ -291,7 +285,7 @@ public class MetadataTest extends AbstractTest {
    */
   @Test
   public void fromdoc2() {
-    final XMLMetadata metadata = getClient().getDeserializer(ContentType.APPLICATION_XML)
+    final XMLMetadata metadata = client.getDeserializer(ContentType.APPLICATION_XML)
         .toMetadata(getClass().getResourceAsStream("fromdoc2-metadata.xml"));
     assertNotNull(metadata);
 
@@ -336,7 +330,7 @@ public class MetadataTest extends AbstractTest {
    */
   @Test
   public void fromdoc3() {
-    final Edm edm = getClient().getReader().readMetadata(getClass().getResourceAsStream("fromdoc3-metadata.xml"));
+    final Edm edm = client.getReader().readMetadata(getClass().getResourceAsStream("fromdoc3-metadata.xml"));
     assertNotNull(edm);
 
     final EdmAnnotations group = edm.getSchema("Annotations").getAnnotationGroups().get(0);
@@ -354,7 +348,7 @@ public class MetadataTest extends AbstractTest {
    */
   @Test
   public void fromdoc4() {
-    final XMLMetadata metadata = getClient().getDeserializer(ContentType.APPLICATION_XML).
+    final XMLMetadata metadata = client.getDeserializer(ContentType.APPLICATION_XML).
         toMetadata(getClass().getResourceAsStream("fromdoc4-metadata.xml"));
     assertNotNull(metadata);
 
@@ -382,7 +376,7 @@ public class MetadataTest extends AbstractTest {
     assertTrue(urlRef.getValue().asDynamic().isApply());
 
     // Now let's go high-level
-    final Edm edm = getClient().getReader().readMetadata(getClass().getResourceAsStream("fromdoc4-metadata.xml"));
+    final Edm edm = client.getReader().readMetadata(getClass().getResourceAsStream("fromdoc4-metadata.xml"));
     assertNotNull(edm);
 
     final EdmAnnotations edmGroup = edm.getSchemas().get(0).getAnnotationGroups().get(0);
@@ -410,8 +404,7 @@ public class MetadataTest extends AbstractTest {
   @Test
   public void metadataWithCapabilities() throws Exception {
     InputStream input = getClass().getResourceAsStream("Metadata-With-Capabilities.xml");
-    final XMLMetadata metadata = getClient().getDeserializer(ContentType.APPLICATION_XML).
-        toMetadata(input);
+    final XMLMetadata metadata = client.getDeserializer(ContentType.APPLICATION_XML).toMetadata(input);
 
     CsdlSchema schema = metadata.getSchema("Capabilities");
     assertNotNull(schema);

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/lib/client-core/src/test/java/org/apache/olingo/client/core/PrimitiveValueTest.java
----------------------------------------------------------------------
diff --git a/lib/client-core/src/test/java/org/apache/olingo/client/core/PrimitiveValueTest.java b/lib/client-core/src/test/java/org/apache/olingo/client/core/PrimitiveValueTest.java
index f46f272..3c31b55 100644
--- a/lib/client-core/src/test/java/org/apache/olingo/client/core/PrimitiveValueTest.java
+++ b/lib/client-core/src/test/java/org/apache/olingo/client/core/PrimitiveValueTest.java
@@ -18,31 +18,25 @@
  */
 package org.apache.olingo.client.core;
 
-import org.apache.olingo.client.api.ODataClient;
+import static org.junit.Assert.assertEquals;
+
+import java.util.Calendar;
+
 import org.apache.olingo.client.api.domain.ClientValue;
 import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
 import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
 import org.junit.Test;
 
-import java.util.Calendar;
-
-import static org.junit.Assert.assertEquals;
-
 public class PrimitiveValueTest extends AbstractTest {
 
-  @Override
-  protected ODataClient getClient() {
-    return v4Client;
-  }
-
   @Test
   public void timeOfDay() throws EdmPrimitiveTypeException {
     final Calendar expected = Calendar.getInstance();
     expected.clear();
     expected.set(2013, 0, 10, 21, 45, 17);
 
-    final ClientValue value = getClient().getObjectFactory().newPrimitiveValueBuilder().
-            setType(EdmPrimitiveTypeKind.TimeOfDay).setValue(expected).build();
+    final ClientValue value = client.getObjectFactory().newPrimitiveValueBuilder()
+        .setType(EdmPrimitiveTypeKind.TimeOfDay).setValue(expected).build();
     assertEquals(EdmPrimitiveTypeKind.TimeOfDay, value.asPrimitive().getTypeKind());
 
     final Calendar actual = value.asPrimitive().toCastValue(Calendar.class);
@@ -59,8 +53,8 @@ public class PrimitiveValueTest extends AbstractTest {
     expected.clear();
     expected.set(2013, 0, 10);
 
-    final ClientValue value = getClient().getObjectFactory().newPrimitiveValueBuilder().
-            setType(EdmPrimitiveTypeKind.Date).setValue(expected).build();
+    final ClientValue value = client.getObjectFactory().newPrimitiveValueBuilder()
+        .setType(EdmPrimitiveTypeKind.Date).setValue(expected).build();
     assertEquals(EdmPrimitiveTypeKind.Date, value.asPrimitive().getTypeKind());
 
     final Calendar actual = value.asPrimitive().toCastValue(Calendar.class);

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/lib/client-core/src/test/java/org/apache/olingo/client/core/PropertyTest.java
----------------------------------------------------------------------
diff --git a/lib/client-core/src/test/java/org/apache/olingo/client/core/PropertyTest.java b/lib/client-core/src/test/java/org/apache/olingo/client/core/PropertyTest.java
index a545dc2..e7dc9ce 100644
--- a/lib/client-core/src/test/java/org/apache/olingo/client/core/PropertyTest.java
+++ b/lib/client-core/src/test/java/org/apache/olingo/client/core/PropertyTest.java
@@ -25,35 +25,29 @@ import static org.junit.Assert.assertTrue;
 import java.io.InputStream;
 import java.util.Iterator;
 
-import org.apache.olingo.client.api.ODataClient;
 import org.apache.olingo.client.api.domain.ClientCollectionValue;
 import org.apache.olingo.client.api.domain.ClientComplexValue;
 import org.apache.olingo.client.api.domain.ClientProperty;
 import org.apache.olingo.client.api.domain.ClientValue;
-import org.apache.olingo.commons.api.format.ContentType;
 import org.apache.olingo.client.api.serialization.ODataDeserializerException;
 import org.apache.olingo.client.api.serialization.ODataSerializerException;
+import org.apache.olingo.commons.api.format.ContentType;
 import org.junit.Test;
 
 public class PropertyTest extends AbstractTest {
 
-  @Override
-  protected ODataClient getClient() {
-    return v4Client;
-  }
-
   private void _enum(final ContentType contentType) throws ODataDeserializerException, ODataSerializerException {
     final InputStream input = getClass().getResourceAsStream("Products_5_SkinColor." + getSuffix(contentType));
-    final ClientProperty property = getClient().getReader().readProperty(input, contentType);
+    final ClientProperty property = client.getReader().readProperty(input, contentType);
     assertNotNull(property);
     assertTrue(property.hasEnumValue());
 
-    final ClientProperty written = getClient().getReader().readProperty(
-            getClient().getWriter().writeProperty(property, contentType), contentType);
+    final ClientProperty written = client.getReader().readProperty(
+            client.getWriter().writeProperty(property, contentType), contentType);
     // This is needed because type information gets lost with serialization
     if (contentType.isCompatible(ContentType.APPLICATION_XML)) {
-      final ClientProperty comparable = getClient().getObjectFactory().newEnumProperty(property.getName(),
-              getClient().getObjectFactory().
+      final ClientProperty comparable = client.getObjectFactory().newEnumProperty(property.getName(),
+              client.getObjectFactory().
               newEnumValue(property.getEnumValue().getTypeName(), written.getEnumValue().getValue()));
 
       assertEquals(property, comparable);
@@ -72,21 +66,21 @@ public class PropertyTest extends AbstractTest {
 
   private void complex(final ContentType contentType) throws ODataDeserializerException, ODataSerializerException {
     final InputStream input = getClass().getResourceAsStream("Employees_3_HomeAddress." + getSuffix(contentType));
-    final ClientProperty property = getClient().getReader().readProperty(input, contentType);
+    final ClientProperty property = client.getReader().readProperty(input, contentType);
     assertNotNull(property);
     assertTrue(property.hasComplexValue());
     assertEquals(3, property.getComplexValue().size());
 
-    final ClientProperty written = getClient().getReader().readProperty(
-            getClient().getWriter().writeProperty(property, contentType), contentType);
+    final ClientProperty written = client.getReader().readProperty(
+            client.getWriter().writeProperty(property, contentType), contentType);
     // This is needed because type information gets lost with JSON serialization
-    final ClientComplexValue typedValue = getClient().getObjectFactory().
+    final ClientComplexValue typedValue = client.getObjectFactory().
             newComplexValue(property.getComplexValue().getTypeName());
     for (final Iterator<ClientProperty> itor = written.getComplexValue().iterator(); itor.hasNext();) {
       final ClientProperty prop = itor.next();
       typedValue.add(prop);
     }
-    final ClientProperty comparable = getClient().getObjectFactory().
+    final ClientProperty comparable = client.getObjectFactory().
             newComplexProperty(property.getName(), typedValue);
 
     assertEquals(property, comparable);
@@ -104,22 +98,22 @@ public class PropertyTest extends AbstractTest {
 
   private void collection(final ContentType contentType) throws ODataDeserializerException, ODataSerializerException {
     final InputStream input = getClass().getResourceAsStream("Products_5_CoverColors." + getSuffix(contentType));
-    final ClientProperty property = getClient().getReader().readProperty(input, contentType);
+    final ClientProperty property = client.getReader().readProperty(input, contentType);
     assertNotNull(property);
     assertTrue(property.hasCollectionValue());
     assertEquals(3, property.getCollectionValue().size());
 
-    final ClientProperty written = getClient().getReader().readProperty(
-            getClient().getWriter().writeProperty(property, contentType), contentType);
+    final ClientProperty written = client.getReader().readProperty(
+            client.getWriter().writeProperty(property, contentType), contentType);
     // This is needed because type information gets lost with JSON serialization
     if(contentType.isCompatible(ContentType.APPLICATION_XML)) {
-      final ClientCollectionValue<ClientValue> typedValue = getClient().getObjectFactory().
+      final ClientCollectionValue<ClientValue> typedValue = client.getObjectFactory().
               newCollectionValue(property.getCollectionValue().getTypeName());
       for (final Iterator<ClientValue> itor = written.getCollectionValue().iterator(); itor.hasNext();) {
         final ClientValue value = itor.next();
         typedValue.add(value);
       }
-      final ClientProperty comparable = getClient().getObjectFactory().
+      final ClientProperty comparable = client.getObjectFactory().
               newCollectionProperty(property.getName(), typedValue);
 
       assertEquals(property, comparable);

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/lib/client-core/src/test/java/org/apache/olingo/client/core/ServiceDocumentTest.java
----------------------------------------------------------------------
diff --git a/lib/client-core/src/test/java/org/apache/olingo/client/core/ServiceDocumentTest.java b/lib/client-core/src/test/java/org/apache/olingo/client/core/ServiceDocumentTest.java
index ae06f90..7a66fac 100644
--- a/lib/client-core/src/test/java/org/apache/olingo/client/core/ServiceDocumentTest.java
+++ b/lib/client-core/src/test/java/org/apache/olingo/client/core/ServiceDocumentTest.java
@@ -24,7 +24,6 @@ import static org.junit.Assert.assertTrue;
 
 import java.net.URI;
 
-import org.apache.olingo.client.api.ODataClient;
 import org.apache.olingo.client.api.data.ResWrap;
 import org.apache.olingo.client.api.data.ServiceDocument;
 import org.apache.olingo.client.api.domain.ClientServiceDocument;
@@ -34,23 +33,14 @@ import org.junit.Test;
 
 public class ServiceDocumentTest extends AbstractTest {
 
-  @Override
-  protected ODataClient getClient() {
-    return v4Client;
-  }
-
-  private String getFileExtension(final ContentType contentType) {
-    return contentType.isCompatible(ContentType.APPLICATION_XML) ? "xml" : "json";
-  }
-
   private ClientServiceDocument parse(final ContentType contentType) throws ODataDeserializerException {
-    ResWrap<ServiceDocument> service = getClient().getDeserializer(contentType).toServiceDocument(
-        getClass().getResourceAsStream("serviceDocument." + getFileExtension(contentType)));
+    ResWrap<ServiceDocument> service = client.getDeserializer(contentType).toServiceDocument(
+        getClass().getResourceAsStream("serviceDocument." + getSuffix(contentType)));
 
     assertEquals(URI.create("http://host/service/$metadata"), service.getContextURL());
     assertEquals("W/\"MjAxMy0wNS0xM1QxNDo1NFo=\"", service.getMetadataETag());
 
-    final ClientServiceDocument serviceDocument = getClient().getBinder().getODataServiceDocument(service.getPayload());
+    final ClientServiceDocument serviceDocument = client.getBinder().getODataServiceDocument(service.getPayload());
     assertNotNull(serviceDocument);
 
     assertTrue(serviceDocument.getEntitySetNames().contains("Order Details"));

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/lib/client-core/src/test/java/org/apache/olingo/client/core/uri/FilterFactoryTest.java
----------------------------------------------------------------------
diff --git a/lib/client-core/src/test/java/org/apache/olingo/client/core/uri/FilterFactoryTest.java b/lib/client-core/src/test/java/org/apache/olingo/client/core/uri/FilterFactoryTest.java
index 1d26f81..3b2c294 100644
--- a/lib/client-core/src/test/java/org/apache/olingo/client/core/uri/FilterFactoryTest.java
+++ b/lib/client-core/src/test/java/org/apache/olingo/client/core/uri/FilterFactoryTest.java
@@ -25,7 +25,6 @@ import java.net.URLEncoder;
 import java.util.Calendar;
 import java.util.TimeZone;
 
-import org.apache.olingo.client.api.ODataClient;
 import org.apache.olingo.client.api.uri.FilterArgFactory;
 import org.apache.olingo.client.api.uri.FilterFactory;
 import org.apache.olingo.client.api.uri.URIFilter;
@@ -39,13 +38,8 @@ import org.junit.Test;
 
 public class FilterFactoryTest extends AbstractTest {
 
-  @Override
-  protected ODataClient getClient() {
-    return v4Client;
-  }
-
   private FilterFactory getFilterFactory() {
-    return getClient().getFilterFactory();
+    return client.getFilterFactory();
   }
 
   private FilterArgFactory getFilterArgFactory() {

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/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 2af662f..5f9cc8b 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
@@ -26,32 +26,25 @@ import java.util.Collections;
 import java.util.LinkedHashMap;
 import java.util.Map;
 
-import org.apache.olingo.client.api.ODataClient;
 import org.apache.olingo.client.api.uri.QueryOption;
 import org.apache.olingo.client.api.uri.URIBuilder;
 import org.apache.olingo.client.core.AbstractTest;
-import org.apache.olingo.client.core.uri.ParameterAlias;
 import org.junit.Test;
 
 public class URIBuilderTest extends AbstractTest {
 
   private static final String SERVICE_ROOT = "http://host/service";
 
-  @Override
-  protected ODataClient getClient() {
-    return v4Client;
-  }
-
   @Test
   public void metadata() throws URISyntaxException {
-    final URI uri = getClient().newURIBuilder(SERVICE_ROOT).appendMetadataSegment().build();
+    final URI uri = client.newURIBuilder(SERVICE_ROOT).appendMetadataSegment().build();
 
     assertEquals(new org.apache.http.client.utils.URIBuilder(SERVICE_ROOT + "/$metadata").build(), uri);
   }
 
   @Test
   public void entity() throws URISyntaxException {
-    final URI uri = getClient().newURIBuilder(SERVICE_ROOT).appendEntitySetSegment("AnEntitySet").
+    final URI uri = client.newURIBuilder(SERVICE_ROOT).appendEntitySetSegment("AnEntitySet").
         appendKeySegment(11).build();
 
     assertEquals(new org.apache.http.client.utils.URIBuilder(SERVICE_ROOT + "/AnEntitySet(11)").build(), uri);
@@ -59,21 +52,21 @@ public class URIBuilderTest extends AbstractTest {
     final Map<String, Object> multiKey = new LinkedHashMap<String, Object>();
     multiKey.put("OrderId", -10);
     multiKey.put("ProductId", -10);
-    URIBuilder uriBuilder = getClient().newURIBuilder(SERVICE_ROOT).
+    URIBuilder uriBuilder = client.newURIBuilder(SERVICE_ROOT).
         appendEntitySetSegment("OrderLine").appendKeySegment(multiKey).
         appendPropertySegment("Quantity").appendValueSegment();
 
     assertEquals(new org.apache.http.client.utils.URIBuilder(
         SERVICE_ROOT + "/OrderLine(OrderId=-10,ProductId=-10)/Quantity/$value").build(), uriBuilder.build());
 
-    uriBuilder = getClient().newURIBuilder(SERVICE_ROOT).
+    uriBuilder = client.newURIBuilder(SERVICE_ROOT).
         appendEntitySetSegment("Customer").appendKeySegment(-10).
         select("CustomerId", "Name", "Orders").expand("Orders");
     assertEquals(new org.apache.http.client.utils.URIBuilder(SERVICE_ROOT + "/Customer(-10)").
         addParameter("$select", "CustomerId,Name,Orders").addParameter("$expand", "Orders").build(),
         uriBuilder.build());
 
-    uriBuilder = getClient().newURIBuilder(SERVICE_ROOT).
+    uriBuilder = client.newURIBuilder(SERVICE_ROOT).
         appendEntitySetSegment("Customer").appendKeySegment(-10).appendNavigationSegment("Orders").appendRefSegment();
     assertEquals(new org.apache.http.client.utils.URIBuilder(SERVICE_ROOT + "/Customer(-10)/Orders/$ref").build(),
         uriBuilder.build());
@@ -81,7 +74,7 @@ public class URIBuilderTest extends AbstractTest {
 
   @Test
   public void expandWithOptions() throws URISyntaxException {
-    final URI uri = getClient().newURIBuilder(SERVICE_ROOT).appendEntitySetSegment("Products").appendKeySegment(5).
+    final URI uri = client.newURIBuilder(SERVICE_ROOT).appendEntitySetSegment("Products").appendKeySegment(5).
         expandWithOptions("ProductDetails", new LinkedHashMap<QueryOption, Object>() {
           private static final long serialVersionUID = 3109256773218160485L;
 
@@ -96,7 +89,7 @@ public class URIBuilderTest extends AbstractTest {
   }
 
   public void expandWithLevels() throws URISyntaxException {
-    final URI uri = getClient().newURIBuilder(SERVICE_ROOT).appendEntitySetSegment("Products").appendKeySegment(1).
+    final URI uri = client.newURIBuilder(SERVICE_ROOT).appendEntitySetSegment("Products").appendKeySegment(1).
         expandWithOptions("Customer", Collections.<QueryOption, Object> singletonMap(QueryOption.LEVELS, 4)).
         build();
 
@@ -106,11 +99,11 @@ public class URIBuilderTest extends AbstractTest {
 
   @Test
   public void count() throws URISyntaxException {
-    URI uri = getClient().newURIBuilder(SERVICE_ROOT).appendEntitySetSegment("Products").count().build();
+    URI uri = client.newURIBuilder(SERVICE_ROOT).appendEntitySetSegment("Products").count().build();
 
     assertEquals(new org.apache.http.client.utils.URIBuilder(SERVICE_ROOT + "/Products/$count").build(), uri);
 
-    uri = getClient().newURIBuilder(SERVICE_ROOT).appendEntitySetSegment("Products").count(true).build();
+    uri = client.newURIBuilder(SERVICE_ROOT).appendEntitySetSegment("Products").count(true).build();
 
     assertEquals(new org.apache.http.client.utils.URIBuilder(SERVICE_ROOT + "/Products").
         addParameter("$count", "true").build(), uri);
@@ -118,34 +111,34 @@ public class URIBuilderTest extends AbstractTest {
 
   @Test
   public void filter() throws URISyntaxException {
-    final URIBuilder uriBuilder = getClient().newURIBuilder(SERVICE_ROOT).appendEntitySetSegment("AnEntitySet").
-        filter(getClient().getFilterFactory().lt("VIN", 16));
+    final URIBuilder uriBuilder = client.newURIBuilder(SERVICE_ROOT).appendEntitySetSegment("AnEntitySet").
+        filter(client.getFilterFactory().lt("VIN", 16));
 
     assertEquals("http://host/service/AnEntitySet?%24filter=%28VIN%20lt%2016%29", uriBuilder.build().toASCIIString());
 
-//    assertEquals(new org.apache.http.client.utils.URIBuilder(SERVICE_ROOT + "/AnEntitySet").
-//        addParameter("$filter", "(VIN lt 16)").build(),
-//        uriBuilder.build());
+    //    assertEquals(new org.apache.http.client.utils.URIBuilder(SERVICE_ROOT + "/AnEntitySet").
+    //        addParameter("$filter", "(VIN lt 16)").build(),
+    //        uriBuilder.build());
   }
 
   @Test
   public void filterWithParameter() throws URISyntaxException {
     // http://host/service.svc/Employees?$filter=Region eq @p1&@p1='WA'
-    final URIBuilder uriBuilder = getClient().newURIBuilder(SERVICE_ROOT).appendEntitySetSegment("Employees").
-        filter(getClient().getFilterFactory().eq("Region", new ParameterAlias("p1"))).
+    final URIBuilder uriBuilder = client.newURIBuilder(SERVICE_ROOT).appendEntitySetSegment("Employees").
+        filter(client.getFilterFactory().eq("Region", new ParameterAlias("p1"))).
         addParameterAlias("p1", "'WA'");
 
     assertEquals("http://host/service/Employees?%24filter=%28Region%20eq%20%40p1%29&%40p1='WA'", uriBuilder.build()
         .toASCIIString());
 
-//    assertEquals(new org.apache.http.client.utils.URIBuilder(SERVICE_ROOT + "/Employees").
-//        addParameter("$filter", "(Region eq @p1)").addParameter("@p1", "'WA'").build(),
-//        uriBuilder.build());
+    //    assertEquals(new org.apache.http.client.utils.URIBuilder(SERVICE_ROOT + "/Employees").
+    //        addParameter("$filter", "(Region eq @p1)").addParameter("@p1", "'WA'").build(),
+    //        uriBuilder.build());
   }
 
   @Test
   public void expandMoreThenOnce() throws URISyntaxException {
-    URI uri = getClient().newURIBuilder(SERVICE_ROOT).appendEntitySetSegment("Products").appendKeySegment(5).
+    URI uri = client.newURIBuilder(SERVICE_ROOT).appendEntitySetSegment("Products").appendKeySegment(5).
         expand("Orders", "Customers").expand("Info").build();
 
     assertEquals(new org.apache.http.client.utils.URIBuilder(SERVICE_ROOT + "/Products(5)").
@@ -154,7 +147,7 @@ public class URIBuilderTest extends AbstractTest {
 
   @Test
   public void selectMoreThenOnce() throws URISyntaxException {
-    URI uri = getClient().newURIBuilder(SERVICE_ROOT).appendEntitySetSegment("Customers").appendKeySegment(5).
+    URI uri = client.newURIBuilder(SERVICE_ROOT).appendEntitySetSegment("Customers").appendKeySegment(5).
         select("Name", "Surname").expand("Info").select("Gender").build();
 
     assertEquals(new org.apache.http.client.utils.URIBuilder(SERVICE_ROOT + "/Customers(5)").
@@ -163,7 +156,7 @@ public class URIBuilderTest extends AbstractTest {
 
   @Test
   public void singleton() throws URISyntaxException {
-    final URIBuilder uriBuilder = getClient().newURIBuilder(SERVICE_ROOT).
+    final URIBuilder uriBuilder = client.newURIBuilder(SERVICE_ROOT).
         appendSingletonSegment("BestProductEverCreated");
 
     assertEquals(new org.apache.http.client.utils.URIBuilder(
@@ -172,7 +165,7 @@ public class URIBuilderTest extends AbstractTest {
 
   @Test
   public void entityId() throws URISyntaxException {
-    final URIBuilder uriBuilder = getClient().newURIBuilder(SERVICE_ROOT).
+    final URIBuilder uriBuilder = client.newURIBuilder(SERVICE_ROOT).
         appendEntityIdSegment("Products(0)");
 
     assertEquals(new org.apache.http.client.utils.URIBuilder(
@@ -181,7 +174,7 @@ public class URIBuilderTest extends AbstractTest {
 
   @Test
   public void boundAction() throws URISyntaxException {
-    final URIBuilder uriBuilder = getClient().newURIBuilder(SERVICE_ROOT).
+    final URIBuilder uriBuilder = client.newURIBuilder(SERVICE_ROOT).
         appendEntitySetSegment("Categories").appendKeySegment(1).
         appendNavigationSegment("Products").
         appendActionCallSegment("Model.AllOrders");
@@ -189,10 +182,10 @@ public class URIBuilderTest extends AbstractTest {
     assertEquals(new org.apache.http.client.utils.URIBuilder(
         SERVICE_ROOT + "/Categories(1)/Products/Model.AllOrders").build(), uriBuilder.build());
   }
-  
+
   @Test
   public void boundOperation() throws URISyntaxException {
-    final URIBuilder uriBuilder = getClient().newURIBuilder(SERVICE_ROOT).
+    final URIBuilder uriBuilder = client.newURIBuilder(SERVICE_ROOT).
         appendEntitySetSegment("Categories").appendKeySegment(1).
         appendNavigationSegment("Products").
         appendOperationCallSegment("Model.AllOrders");
@@ -203,14 +196,14 @@ public class URIBuilderTest extends AbstractTest {
 
   @Test
   public void ref() throws URISyntaxException {
-    URIBuilder uriBuilder = getClient().newURIBuilder(SERVICE_ROOT).
+    URIBuilder uriBuilder = client.newURIBuilder(SERVICE_ROOT).
         appendEntitySetSegment("Categories").appendKeySegment(1).
         appendNavigationSegment("Products").appendRefSegment();
 
     assertEquals(new org.apache.http.client.utils.URIBuilder(
         SERVICE_ROOT + "/Categories(1)/Products/$ref").build(), uriBuilder.build());
 
-    uriBuilder = getClient().newURIBuilder(SERVICE_ROOT).
+    uriBuilder = client.newURIBuilder(SERVICE_ROOT).
         appendEntitySetSegment("Categories").appendKeySegment(1).
         appendNavigationSegment("Products").appendRefSegment().id("../../Products(0)");
 
@@ -221,7 +214,7 @@ public class URIBuilderTest extends AbstractTest {
 
   @Test
   public void derived() throws URISyntaxException {
-    final URIBuilder uriBuilder = getClient().newURIBuilder(SERVICE_ROOT).
+    final URIBuilder uriBuilder = client.newURIBuilder(SERVICE_ROOT).
         appendEntitySetSegment("Customers").appendDerivedEntityTypeSegment("Model.VipCustomer").appendKeySegment(1);
 
     assertEquals(new org.apache.http.client.utils.URIBuilder(
@@ -230,7 +223,7 @@ public class URIBuilderTest extends AbstractTest {
 
   @Test
   public void crossjoin() throws URISyntaxException {
-    final URIBuilder uriBuilder = getClient().newURIBuilder(SERVICE_ROOT).
+    final URIBuilder uriBuilder = client.newURIBuilder(SERVICE_ROOT).
         appendCrossjoinSegment("Products", "Sales");
 
     assertEquals(new org.apache.http.client.utils.URIBuilder(
@@ -239,7 +232,7 @@ public class URIBuilderTest extends AbstractTest {
 
   @Test
   public void all() throws URISyntaxException {
-    final URIBuilder uriBuilder = getClient().newURIBuilder(SERVICE_ROOT).appendAllSegment();
+    final URIBuilder uriBuilder = client.newURIBuilder(SERVICE_ROOT).appendAllSegment();
 
     assertEquals(new org.apache.http.client.utils.URIBuilder(
         SERVICE_ROOT + "/$all").build(), uriBuilder.build());
@@ -247,7 +240,7 @@ public class URIBuilderTest extends AbstractTest {
 
   @Test
   public void search() throws URISyntaxException {
-    final URIBuilder uriBuilder = getClient().newURIBuilder(SERVICE_ROOT).
+    final URIBuilder uriBuilder = client.newURIBuilder(SERVICE_ROOT).
         appendEntitySetSegment("Products").search("blue OR green");
 
     assertEquals(new URI("http://host/service/Products?%24search=blue%20OR%20green"), uriBuilder.build());

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/lib/commons-api/src/main/java/org/apache/olingo/commons/api/edm/geo/Geospatial.java
----------------------------------------------------------------------
diff --git a/lib/commons-api/src/main/java/org/apache/olingo/commons/api/edm/geo/Geospatial.java b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/edm/geo/Geospatial.java
index 63d8b3f..860cbcc 100644
--- a/lib/commons-api/src/main/java/org/apache/olingo/commons/api/edm/geo/Geospatial.java
+++ b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/edm/geo/Geospatial.java
@@ -72,7 +72,6 @@ public abstract class Geospatial {
      * The OGIS geometry type number for feature collections.
      */
     GEOSPATIALCOLLECTION
-
   }
 
   protected final Dimension dimension;
@@ -87,8 +86,8 @@ public abstract class Geospatial {
   /**
    * Constructor.
    *
-   * @param dimension dimension.
-   * @param type type.
+   * @param dimension dimension
+   * @param type type
    * @param srid SRID
    */
   protected Geospatial(final Dimension dimension, final Type type, final SRID srid) {
@@ -129,7 +128,7 @@ public abstract class Geospatial {
 
   /**
    * Returns the {@link EdmPrimitiveTypeKind}
-   * @return Edm primitve type kind
+   * @return EDM primitive type kind
    */
   public abstract EdmPrimitiveTypeKind getEdmPrimitiveTypeKind();
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/EdmNavigationPropertyImpl.java
----------------------------------------------------------------------
diff --git a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/EdmNavigationPropertyImpl.java b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/EdmNavigationPropertyImpl.java
index bf5dbc6..05abab9 100644
--- a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/EdmNavigationPropertyImpl.java
+++ b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/EdmNavigationPropertyImpl.java
@@ -23,7 +23,6 @@ import java.util.Collections;
 import java.util.List;
 
 import org.apache.olingo.commons.api.edm.Edm;
-import org.apache.olingo.commons.api.edm.EdmElement;
 import org.apache.olingo.commons.api.edm.EdmEntityType;
 import org.apache.olingo.commons.api.edm.EdmException;
 import org.apache.olingo.commons.api.edm.EdmNavigationProperty;
@@ -32,7 +31,7 @@ import org.apache.olingo.commons.api.edm.EdmStructuredType;
 import org.apache.olingo.commons.api.edm.provider.CsdlNavigationProperty;
 import org.apache.olingo.commons.api.edm.provider.CsdlReferentialConstraint;
 
-public class EdmNavigationPropertyImpl extends AbstractEdmNamed implements EdmElement, EdmNavigationProperty {
+public class EdmNavigationPropertyImpl extends AbstractEdmNamed implements EdmNavigationProperty {
 
   private final CsdlNavigationProperty navigationProperty;
   private List<EdmReferentialConstraint> referentialConstraints;

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/EdmParameterImpl.java
----------------------------------------------------------------------
diff --git a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/EdmParameterImpl.java b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/EdmParameterImpl.java
index 69af130..2f67761 100644
--- a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/EdmParameterImpl.java
+++ b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/EdmParameterImpl.java
@@ -19,7 +19,6 @@
 package org.apache.olingo.commons.core.edm;
 
 import org.apache.olingo.commons.api.edm.Edm;
-import org.apache.olingo.commons.api.edm.EdmElement;
 import org.apache.olingo.commons.api.edm.EdmException;
 import org.apache.olingo.commons.api.edm.EdmMapping;
 import org.apache.olingo.commons.api.edm.EdmParameter;
@@ -27,7 +26,7 @@ import org.apache.olingo.commons.api.edm.EdmType;
 import org.apache.olingo.commons.api.edm.geo.SRID;
 import org.apache.olingo.commons.api.edm.provider.CsdlParameter;
 
-public class EdmParameterImpl extends AbstractEdmNamed implements EdmParameter, EdmElement {
+public class EdmParameterImpl extends AbstractEdmNamed implements EdmParameter {
 
   private final CsdlParameter parameter;
   private EdmType typeImpl;

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/EdmPropertyImpl.java
----------------------------------------------------------------------
diff --git a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/EdmPropertyImpl.java b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/EdmPropertyImpl.java
index 5385d8a..67d0a21 100644
--- a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/EdmPropertyImpl.java
+++ b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/EdmPropertyImpl.java
@@ -19,7 +19,6 @@
 package org.apache.olingo.commons.core.edm;
 
 import org.apache.olingo.commons.api.edm.Edm;
-import org.apache.olingo.commons.api.edm.EdmElement;
 import org.apache.olingo.commons.api.edm.EdmException;
 import org.apache.olingo.commons.api.edm.EdmMapping;
 import org.apache.olingo.commons.api.edm.EdmProperty;
@@ -27,7 +26,7 @@ import org.apache.olingo.commons.api.edm.EdmType;
 import org.apache.olingo.commons.api.edm.geo.SRID;
 import org.apache.olingo.commons.api.edm.provider.CsdlProperty;
 
-public class EdmPropertyImpl extends AbstractEdmNamed implements EdmProperty, EdmElement {
+public class EdmPropertyImpl extends AbstractEdmNamed implements EdmProperty {
 
   private final CsdlProperty property;
   private EdmTypeInfo typeInfo;
@@ -59,7 +58,7 @@ public class EdmPropertyImpl extends AbstractEdmNamed implements EdmProperty, Ed
     if (property.getType() == null) {
       throw new EdmException("Property " + property.getName() + " must hava a full qualified type.");
     }
-    typeInfo = new EdmTypeInfo.Builder().setEdm(edm).setTypeExpression(property.getType().toString()).build();
+    typeInfo = new EdmTypeInfo.Builder().setEdm(edm).setTypeExpression(property.getType()).build();
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/lib/server-core/src/main/java/org/apache/olingo/server/core/batchhandler/BatchFacadeImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/batchhandler/BatchFacadeImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/batchhandler/BatchFacadeImpl.java
index 9fe52c8..98bf563 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/batchhandler/BatchFacadeImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/batchhandler/BatchFacadeImpl.java
@@ -33,20 +33,26 @@ import org.apache.olingo.server.core.deserializer.batch.BatchParserCommon;
 public class BatchFacadeImpl implements BatchFacade {
   private final BatchPartHandler partHandler;
 
-  public BatchFacadeImpl(final ODataHandler oDataHandler, final ODataRequest request,
-      final BatchProcessor batchProcessor, final boolean isStrict) {
+  /**
+   * Creates a new BatchFacade.
+   * @param oDataHandler   handler
+   * @param batchProcessor batch processor
+   * @param isStrict       mode switch (currently not used)
+   */
+  public BatchFacadeImpl(final ODataHandler oDataHandler, final BatchProcessor batchProcessor,
+      final boolean isStrict) {
     partHandler = new BatchPartHandler(oDataHandler, batchProcessor, this);
   }
 
   @Override
-  public ODataResponse handleODataRequest(final ODataRequest request) throws ODataApplicationException,
-  ODataLibraryException {
+  public ODataResponse handleODataRequest(final ODataRequest request)
+      throws ODataApplicationException, ODataLibraryException {
     return partHandler.handleODataRequest(request);
   }
 
   @Override
-  public ODataResponsePart handleBatchRequest(final BatchRequestPart request) throws ODataApplicationException,
-  ODataLibraryException {
+  public ODataResponsePart handleBatchRequest(final BatchRequestPart request)
+      throws ODataApplicationException, ODataLibraryException {
     return partHandler.handleBatchRequest(request);
   }
 

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/lib/server-core/src/main/java/org/apache/olingo/server/core/batchhandler/BatchHandler.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/batchhandler/BatchHandler.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/batchhandler/BatchHandler.java
index ca253dc..121734e 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/batchhandler/BatchHandler.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/batchhandler/BatchHandler.java
@@ -46,7 +46,7 @@ public class BatchHandler {
       throws ODataApplicationException, ODataLibraryException {
     validateRequest(request);
 
-    final BatchFacade operation = new BatchFacadeImpl(oDataHandler, request, batchProcessor, isStrict);
+    final BatchFacade operation = new BatchFacadeImpl(oDataHandler, batchProcessor, isStrict);
     batchProcessor.processBatch(operation, request, response);
   }
 


[19/22] olingo-odata4 git commit: OLINGO-864: Refining the Edm.Date and Edm.Time behavior not to assume GMT but use default timezone of the JVM

Posted by mi...@apache.org.
OLINGO-864: Refining the Edm.Date and Edm.Time behavior not to assume GMT but use default timezone of the JVM


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

Branch: refs/heads/OLINGO-832_StreamSerializerPoC
Commit: 7b26cc6ee7515b4f2657fe9756862882ead7f26d
Parents: b317b90 f63bba7
Author: Ramesh Reddy <ra...@jboss.org>
Authored: Wed Feb 3 11:49:52 2016 -0600
Committer: Ramesh Reddy <ra...@jboss.org>
Committed: Wed Feb 10 13:04:42 2016 -0600

----------------------------------------------------------------------
 .../client/AbstractParamTecSvcITCase.java       | 14 +++++
 .../commons/core/edm/primitivetype/EdmDate.java |  5 +-
 .../edm/primitivetype/EdmDateTimeOffset.java    | 62 ++++++++++++--------
 .../core/edm/primitivetype/EdmTimeOfDay.java    | 20 ++-----
 .../core/edm/primitivetype/EdmDateTest.java     |  1 -
 .../primitivetype/EdmDateTimeOffsetTest.java    |  9 ++-
 .../edm/primitivetype/EdmTimeOfDayTest.java     | 23 ++++++--
 .../olingo/server/tecsvc/data/DataCreator.java  | 10 +++-
 .../server/tecsvc/data/DataProviderTest.java    | 14 +++++
 .../json/ODataJsonSerializerTest.java           | 13 ++++
 10 files changed, 116 insertions(+), 55 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7b26cc6e/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/AbstractParamTecSvcITCase.java
----------------------------------------------------------------------
diff --cc fit/src/test/java/org/apache/olingo/fit/tecsvc/client/AbstractParamTecSvcITCase.java
index d6e35a3,a4d8a67..dc2b940
--- a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/AbstractParamTecSvcITCase.java
+++ b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/AbstractParamTecSvcITCase.java
@@@ -63,4 -67,14 +67,14 @@@ public abstract class AbstractParamTecS
      assertTrue(n instanceof Number);
      assertEquals(value, ((Number) n).intValue());
    }
+   
+   @Before
+   public void setup() {
 -    DataProvider.setDefaultTimeZone("GMT");
++    TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
+   }
+   
+   @After
+   public void teardown() {
 -    DataProvider.setDefaultTimeZone(TimeZone.getDefault().getID());
++    TimeZone.setDefault(TimeZone.getDefault());
+   }  
  }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7b26cc6e/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDate.java
----------------------------------------------------------------------
diff --cc lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDate.java
index 3eddca0,8588a5c..b0903ed
--- a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDate.java
+++ b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDate.java
@@@ -48,7 -47,7 +47,7 @@@ public final class EdmDate extends Sing
        final Boolean isNullable, final Integer maxLength, final Integer precision,
        final Integer scale, final Boolean isUnicode, final Class<T> returnType) throws EdmPrimitiveTypeException {
  
-     final Calendar dateTimeValue = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
 -    final Calendar dateTimeValue = Calendar.getInstance(EdmDateTimeOffset.getDefaultTimeZone());
++    final Calendar dateTimeValue = Calendar.getInstance();
      dateTimeValue.clear();
  
      final Matcher matcher = PATTERN.matcher(value);

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7b26cc6e/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDateTimeOffset.java
----------------------------------------------------------------------
diff --cc lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDateTimeOffset.java
index a7f57d1,63c2c3c..990e1f5
--- a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDateTimeOffset.java
+++ b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDateTimeOffset.java
@@@ -203,21 -211,27 +211,27 @@@ public final class EdmDateTimeOffset ex
     * @return the value as {@link Calendar}
     * @throws EdmPrimitiveTypeException if the type of the value is not supported
     */
-   protected static <T> Calendar createDateTime(final T value) throws EdmPrimitiveTypeException {
+   protected static <T> Calendar createDateTime(final T value, boolean isLocal) throws EdmPrimitiveTypeException {
      Calendar dateTimeValue;
-     if(value instanceof Time) {
-       dateTimeValue = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
-       dateTimeValue.setTimeInMillis(((Time) value).getTime());
-     } else if (value instanceof Date) {
-       // Although java.util.Date, as stated in its documentation,
-       // "is intended to reflect coordinated universal time (UTC)",
-       // its getName() method uses the default time zone. And so do we.
-       dateTimeValue = Calendar.getInstance();
+     if (value instanceof Date) {
+       TimeZone tz;
+       if (isLocal) {
 -        tz = getDefaultTimeZone();
++        tz = TimeZone.getDefault();
+       } else {
+     	tz = TimeZone.getTimeZone("GMT");  
+       }
+       dateTimeValue = Calendar.getInstance(tz);
        dateTimeValue.setTime((Date) value);
      } else if (value instanceof Calendar) {
        dateTimeValue = (Calendar) ((Calendar) value).clone();
      } else if (value instanceof Long) {
-       dateTimeValue = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
+       TimeZone tz;
+       if (isLocal) {
 -        tz = getDefaultTimeZone();
++        tz = TimeZone.getDefault();
+       } else {
+         tz = TimeZone.getTimeZone("GMT");  
+       }
+       dateTimeValue = Calendar.getInstance(tz);
        dateTimeValue.setTimeInMillis((Long) value);
      } else {
        throw new EdmPrimitiveTypeException("The value type " + value.getClass() + " is not supported.");

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7b26cc6e/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmTimeOfDay.java
----------------------------------------------------------------------
diff --cc lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmTimeOfDay.java
index 7595e51,06ba239..de0d8d6
--- a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmTimeOfDay.java
+++ b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmTimeOfDay.java
@@@ -52,7 -51,7 +51,7 @@@ public final class EdmTimeOfDay extend
        throw new EdmPrimitiveTypeException("The literal '" + value + "' has illegal content.");
      }
  
-     final Calendar dateTimeValue = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
 -    final Calendar dateTimeValue = Calendar.getInstance(EdmDateTimeOffset.getDefaultTimeZone());
++    final Calendar dateTimeValue = Calendar.getInstance();
      dateTimeValue.clear();
      dateTimeValue.set(Calendar.HOUR_OF_DAY, Byte.parseByte(matcher.group(1)));
      dateTimeValue.set(Calendar.MINUTE, Byte.parseByte(matcher.group(2)));

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7b26cc6e/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataCreator.java
----------------------------------------------------------------------
diff --cc lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataCreator.java
index 5c60b38,5c60b38..3de7c37
--- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataCreator.java
+++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataCreator.java
@@@ -28,7 -28,7 +28,6 @@@ import java.util.Calendar
  import java.util.HashMap;
  import java.util.List;
  import java.util.Map;
--import java.util.TimeZone;
  import java.util.UUID;
  
  import org.apache.olingo.commons.api.Constants;
@@@ -1187,9 -1187,9 +1186,10 @@@ public class DataCreator 
  
    protected static Calendar getDateTime(final int year, final int month, final int day,
        final int hour, final int minute, final int second) {
--    Calendar dateTime = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
++    Calendar dateTime = Calendar.getInstance();
      dateTime.clear();
      dateTime.set(year, month - 1, day, hour, minute, second);
++    dateTime.set(Calendar.MILLISECOND, 0);
      return dateTime;
    }
  
@@@ -1201,8 -1201,8 +1201,12 @@@
    }
  
    protected static Calendar getTime(final int hour, final int minute, final int second) {
--    Calendar time = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
++    Calendar time = Calendar.getInstance();
      time.clear();
++    time.set(Calendar.YEAR, 1970);
++    time.set(Calendar.MONTH, Calendar.JANUARY);
++    time.set(Calendar.DAY_OF_MONTH, 1);
++    time.set(Calendar.MILLISECOND, 0);    
      time.set(Calendar.HOUR_OF_DAY, hour);
      time.set(Calendar.MINUTE, minute);
      time.set(Calendar.SECOND, second);

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7b26cc6e/lib/server-tecsvc/src/test/java/org/apache/olingo/server/tecsvc/data/DataProviderTest.java
----------------------------------------------------------------------
diff --cc lib/server-tecsvc/src/test/java/org/apache/olingo/server/tecsvc/data/DataProviderTest.java
index 6bd6463,b2bf587..dddafa2
--- a/lib/server-tecsvc/src/test/java/org/apache/olingo/server/tecsvc/data/DataProviderTest.java
+++ b/lib/server-tecsvc/src/test/java/org/apache/olingo/server/tecsvc/data/DataProviderTest.java
@@@ -52,6 -55,16 +55,16 @@@ public class DataProviderTest 
    private final EdmEntitySet esMixPrimCollComp = entityContainer.getEntitySet("ESMixPrimCollComp");
    private final EdmEntitySet esMedia = entityContainer.getEntitySet("ESMedia");
  
+   @Before
+   public void setup() {
 -    DataProvider.setDefaultTimeZone("GMT");
++    TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
+   }
+   
+   @After
+   public void teardown() {
 -    DataProvider.setDefaultTimeZone(TimeZone.getDefault().getID());
 -  }
++    TimeZone.setDefault(TimeZone.getDefault());
++  } 
+   
    @Test
    public void esAllPrimEntity() throws Exception {
      final DataProvider dataProvider = new DataProvider(oData, edm);

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7b26cc6e/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializerTest.java
----------------------------------------------------------------------
diff --cc lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializerTest.java
index 7761b1d,7761b1d..8a7fca4
--- 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
@@@ -22,6 -22,6 +22,7 @@@ import java.io.InputStream
  import java.net.URI;
  import java.util.Arrays;
  import java.util.Collections;
++import java.util.TimeZone;
  
  import org.apache.commons.io.IOUtils;
  import org.apache.olingo.commons.api.data.ComplexValue;
@@@ -62,7 -62,7 +63,9 @@@ import org.apache.olingo.server.tecsvc.
  import org.apache.olingo.server.tecsvc.data.DataProvider;
  import org.apache.olingo.server.tecsvc.provider.EdmTechProvider;
  import org.hamcrest.CoreMatchers;
++import org.junit.After;
  import org.junit.Assert;
++import org.junit.Before;
  import org.junit.Test;
  import org.mockito.Mockito;
  
@@@ -78,6 -78,6 +81,16 @@@ public class ODataJsonSerializerTest 
        new ODataJsonSerializer(ContentType.create(ContentType.JSON, ContentType.PARAMETER_IEEE754_COMPATIBLE, "true"));
    private final UriHelper helper = odata.createUriHelper();
  
++  @Before
++  public void setup() {
++    TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
++  }
++  
++  @After
++  public void teardown() {
++    TimeZone.setDefault(TimeZone.getDefault());
++  }
++  
    @Test
    public void entitySimple() throws Exception {
      final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim");


[22/22] olingo-odata4 git commit: [OLINGO-832] Merge branch 'master' into OLINGO-832_StreamSerializerPoC

Posted by mi...@apache.org.
[OLINGO-832] Merge branch 'master' into OLINGO-832_StreamSerializerPoC


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

Branch: refs/heads/OLINGO-832_StreamSerializerPoC
Commit: 67494a789798911fee97388e204952ff4c357723
Parents: 5174f70 3c205f9
Author: mibo <mi...@apache.org>
Authored: Sat Feb 13 07:28:32 2016 +0100
Committer: mibo <mi...@apache.org>
Committed: Sat Feb 13 07:28:32 2016 +0100

----------------------------------------------------------------------
 .../commons/AbstractInvocationHandler.java      |   17 +-
 .../AbstractStructuredInvocationHandler.java    |    2 +-
 .../commons/AnnotatationsInvocationHandler.java |    2 +-
 .../ComplexCollectionInvocationHandler.java     |    2 +-
 .../proxy/commons/ComplexInvocationHandler.java |    6 +-
 .../proxy/commons/EdmStreamValueHandler.java    |    2 +-
 .../EntityCollectionInvocationHandler.java      |    2 +-
 .../EntityContainerInvocationHandler.java       |    4 +-
 .../proxy/commons/EntityInvocationHandler.java  |    6 +-
 .../commons/EntitySetInvocationHandler.java     |    2 +-
 .../proxy/commons/InvokerInvocationHandler.java |    2 +-
 .../commons/OperationInvocationHandler.java     |    2 +-
 .../PrimitiveCollectionInvocationHandler.java   |    2 +-
 ...turedComposableInvokerInvocationHandler.java |    2 +-
 .../olingo/ext/proxy/utils/CoreUtils.java       |    5 +-
 .../org/apache/olingo/fit/AbstractServices.java | 1947 --------------
 .../main/java/org/apache/olingo/fit/Demo.java   |    6 +-
 .../java/org/apache/olingo/fit/OpenType.java    |    5 +-
 .../java/org/apache/olingo/fit/Services.java    | 2511 +++++++++++++++---
 .../org/apache/olingo/fit/Vocabularies.java     |   10 +-
 .../apache/olingo/fit/metadata/EntitySet.java   |    8 -
 .../olingo/fit/rest/OAuth2RequestFilter.java    |    3 +-
 .../fit/serializer/FITAtomDeserializer.java     |   13 +-
 .../olingo/fit/utils/AbstractUtilities.java     |   22 +-
 .../org/apache/olingo/fit/utils/Accept.java     |   31 +-
 .../org/apache/olingo/fit/utils/Commons.java    |   24 +-
 .../apache/olingo/fit/utils/ConstantKey.java    |   10 +-
 .../org/apache/olingo/fit/utils/Constants.java  |    7 -
 .../org/apache/olingo/fit/utils/FSManager.java  |   25 +-
 .../fit/utils/InjectableSerializerProvider.java |   42 -
 .../apache/olingo/fit/utils/JSONUtilities.java  |   14 +-
 .../olingo/fit/utils/MetadataLinkInfo.java      |  182 --
 .../apache/olingo/fit/utils/XMLUtilities.java   |    3 +
 .../proxy/demo/odatademo/types/Customer.java    |    6 +-
 .../proxy/demo/odatademo/types/Employee.java    |    6 +-
 .../demo/odatademo/types/FeaturedProduct.java   |    6 +-
 .../opentypesservice/types/IndexedRow.java      |    8 +-
 .../odatawcfservice/types/CreditCardPI.java     |    6 +-
 .../odatawcfservice/types/Customer.java         |    6 +-
 .../odatawcfservice/types/Employee.java         |    6 +-
 .../odatawcfservice/types/PublicCompany.java    |    8 +-
 .../client/AbstractParamTecSvcITCase.java       |   14 +
 .../olingo/fit/tecsvc/client/BasicITCase.java   |   34 +-
 .../fit/tecsvc/client/BatchClientITCase.java    |    8 +-
 .../olingo/fit/tecsvc/client/BindingITCase.java |   10 +-
 .../fit/tecsvc/client/DeepInsertITCase.java     |   31 +-
 .../tecsvc/client/EntityReferencesITCase.java   |   13 +-
 .../ExpandWithSystemQueryOptionsITCase.java     |   74 +-
 .../tecsvc/client/FilterSystemQueryITCase.java  |    4 +-
 .../core/domain/AbstractClientEntitySet.java    |  114 -
 .../core/domain/ClientCollectionValueImpl.java  |    2 +-
 .../client/core/domain/ClientEntitySetImpl.java |   74 +-
 .../core/domain/ClientPrimitiveValueImpl.java   |    5 +-
 .../client/core/domain/ClientPropertyImpl.java  |  135 +-
 .../client/core/domain/ClientValuableImpl.java  |   22 +-
 .../core/serialization/ODataBinderImpl.java     |    2 +-
 .../apache/olingo/client/core/AbstractTest.java |    9 +-
 .../org/apache/olingo/client/core/AtomTest.java |    6 -
 .../olingo/client/core/EntitySetTest.java       |   22 +-
 .../apache/olingo/client/core/EntityTest.java   |   73 +-
 .../apache/olingo/client/core/ErrorTest.java    |    8 +-
 .../org/apache/olingo/client/core/JSONTest.java |   46 +-
 .../apache/olingo/client/core/MetadataTest.java |   33 +-
 .../olingo/client/core/PrimitiveValueTest.java  |   22 +-
 .../apache/olingo/client/core/PropertyTest.java |   38 +-
 .../olingo/client/core/ServiceDocumentTest.java |   16 +-
 .../client/core/uri/FilterFactoryTest.java      |    8 +-
 .../olingo/client/core/uri/URIBuilderTest.java  |   71 +-
 .../olingo/commons/api/edm/geo/Geospatial.java  |    7 +-
 .../commons/api/edm/provider/CsdlOnDelete.java  |   23 +-
 .../api/edm/provider/CsdlReturnType.java        |   23 +-
 .../olingo/commons/api/http/HttpHeader.java     |    2 +
 .../olingo/server/api/edmx/EdmxReference.java   |   24 +-
 .../commons/core/edm/EdmEntityTypeImpl.java     |    7 +-
 .../core/edm/EdmNavigationPropertyImpl.java     |    3 +-
 .../commons/core/edm/EdmParameterImpl.java      |    3 +-
 .../commons/core/edm/EdmPropertyImpl.java       |    5 +-
 .../commons/core/edm/primitivetype/EdmDate.java |    5 +-
 .../edm/primitivetype/EdmDateTimeOffset.java    |   62 +-
 .../core/edm/primitivetype/EdmTimeOfDay.java    |   20 +-
 .../core/edm/primitivetype/EdmDateTest.java     |    1 -
 .../primitivetype/EdmDateTimeOffsetTest.java    |    9 +-
 .../edm/primitivetype/EdmTimeOfDayTest.java     |   23 +-
 .../edm/provider/EdmEntityTypeImplTest.java     |   19 +
 .../org/apache/olingo/server/api/OData.java     |   10 +
 .../uri/queryoption/SystemQueryOptionKind.java  |   22 +-
 .../apache/olingo/server/core/ErrorHandler.java |   47 +-
 .../olingo/server/core/MetadataParser.java      |  582 +++-
 .../olingo/server/core/OData4HttpHandler.java   |   10 +-
 .../olingo/server/core/ReferenceResolver.java   |   33 +
 .../server/core/SchemaBasedEdmProvider.java     |  137 +-
 .../olingo/server/core/ServiceDispatcher.java   |   48 +-
 .../olingo/server/core/ServiceHandler.java      |   27 +-
 .../core/legacy/ProcessorServiceHandler.java    |   12 +
 .../server/core/requests/ActionRequest.java     |    2 +-
 .../server/core/requests/BatchRequest.java      |   11 +-
 .../server/core/requests/DataRequest.java       |    6 +-
 .../server/core/responses/EntityResponse.java   |    1 +
 .../core/responses/EntitySetResponse.java       |    2 +
 .../server/core/responses/ErrorResponse.java    |   58 +
 .../server/core/responses/MetadataResponse.java |    2 +
 .../server/core/responses/PropertyResponse.java |    2 +
 .../core/responses/ServiceDocumentResponse.java |    2 +
 .../core/responses/ServiceResponseVisior.java   |    4 +
 .../resources/Org.OData.Capabilities.V1.xml     |  388 +++
 .../src/main/resources/Org.OData.Core.V1.xml    |  187 ++
 .../main/resources/Org.OData.Measures.V1.xml    |  110 +
 .../core/MetadataParserAnnotationsTest.java     |  215 ++
 .../olingo/server/core/MetadataParserTest.java  |    3 +-
 .../server/core/ServiceDispatcherTest.java      |   17 +-
 .../olingo/server/example/TripPinDataModel.java |    2 +-
 .../olingo/server/example/TripPinHandler.java   |   14 +-
 .../server/example/TripPinServiceTest.java      |   10 +
 .../olingo/server/example/TripPinServlet.java   |   11 +-
 .../src/test/resources/annotations.xml          |  153 ++
 .../src/test/resources/trippin.xml              |  808 +++---
 .../apache/olingo/server/core/ODataHandler.java |    4 +-
 .../server/core/ODataHttpHandlerImpl.java       |   19 +-
 .../apache/olingo/server/core/ODataImpl.java    |   13 +
 .../core/batchhandler/BatchFacadeImpl.java      |   18 +-
 .../server/core/batchhandler/BatchHandler.java  |    2 +-
 .../json/ODataJsonDeserializer.java             |   77 +-
 .../deserializer/xml/ODataXmlDeserializer.java  |   84 +-
 .../serializer/json/ODataJsonSerializer.java    |   42 +-
 .../core/serializer/xml/ODataXmlSerializer.java |   18 +-
 .../olingo/server/core/uri/UriInfoImpl.java     |   37 +-
 .../server/core/uri/parser/ExpandParser.java    |   30 +-
 .../core/uri/parser/ExpressionParser.java       |   85 +-
 .../server/core/uri/parser/FilterParser.java    |    6 +-
 .../server/core/uri/parser/OrderByParser.java   |    6 +-
 .../olingo/server/core/uri/parser/Parser.java   |  354 +--
 .../server/core/uri/parser/ParserHelper.java    |  168 +-
 .../core/uri/parser/ResourcePathParser.java     |   38 +-
 .../server/core/uri/parser/SelectParser.java    |   12 +-
 .../server/core/uri/parser/UriTokenizer.java    |   12 +-
 .../uri/queryoption/expression/AliasImpl.java   |    9 +-
 .../uri/validator/UriValidationException.java   |    4 +-
 .../server/core/uri/validator/UriValidator.java |  513 +---
 .../server-core-exceptions-i18n.properties      |    1 +
 .../olingo/server/core/uri/UriInfoImplTest.java |   50 +-
 .../core/uri/parser/ExpressionParserTest.java   |    2 +-
 .../core/uri/parser/UriTokenizerTest.java       |    3 +
 .../olingo/server/tecsvc/data/DataCreator.java  |   27 +-
 .../olingo/server/tecsvc/data/DataProvider.java |   12 +-
 .../SystemQueryOptionsRuntimeException.java     |    3 +-
 .../tecsvc/provider/ComplexTypeProvider.java    |    8 +
 .../tecsvc/provider/ContainerProvider.java      |    6 +-
 .../server/tecsvc/data/DataProviderTest.java    |   14 +
 .../AbstractODataDeserializerTest.java          |    5 +-
 .../ODataDeserializerEntityCollectionTest.java  |    4 +-
 ...ataJsonDeserializerActionParametersTest.java |    2 +-
 .../json/ODataJsonDeserializerEntityTest.java   |   46 +-
 ...DataXMLDeserializerActionParametersTest.java |    2 +-
 .../xml/ODataXmlDeserializerTest.java           |   43 +-
 .../json/ODataJsonSerializerTest.java           |   47 +-
 .../serializer/xml/ODataXmlSerializerTest.java  |   77 +-
 .../core/uri/parser/TestFullResourcePath.java   |  112 +-
 .../core/uri/queryoption/QueryOptionTest.java   |    4 +-
 .../queryoption/expression/ExpressionTest.java  |    6 +-
 .../core/uri/testutil/FilterValidator.java      |   51 +-
 .../core/uri/validator/UriValidatorTest.java    |   68 +-
 161 files changed, 6352 insertions(+), 4831 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/67494a78/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHttpHandlerImpl.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/67494a78/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializer.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/67494a78/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/xml/ODataXmlSerializer.java
----------------------------------------------------------------------


[15/22] olingo-odata4 git commit: OLINGO-865: fixing the bug with extended complex types during serilization

Posted by mi...@apache.org.
OLINGO-865: fixing the bug with extended complex types during serilization


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

Branch: refs/heads/OLINGO-832_StreamSerializerPoC
Commit: 8468308aeb2920e52d56b23101e59b3cf6b0e6f8
Parents: 280bc01
Author: Ramesh Reddy <ra...@jboss.org>
Authored: Sun Feb 7 17:06:22 2016 -0600
Committer: Ramesh Reddy <ra...@jboss.org>
Committed: Sun Feb 7 17:06:22 2016 -0600

----------------------------------------------------------------------
 .../serializer/json/ODataJsonSerializer.java    | 42 +++++++----
 .../core/serializer/xml/ODataXmlSerializer.java | 18 +++--
 .../olingo/server/tecsvc/data/DataCreator.java  | 17 ++++-
 .../tecsvc/provider/ComplexTypeProvider.java    |  8 ++
 .../json/ODataJsonSerializerTest.java           | 34 ++++++++-
 .../serializer/xml/ODataXmlSerializerTest.java  | 77 +++++++++++++++++++-
 6 files changed, 166 insertions(+), 30 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8468308a/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 a912862..3f3ba26 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
@@ -264,7 +264,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
       if (!isODataMetadataNone && !resolvedType.equals(entityType)) {
         json.writeStringField(Constants.JSON_TYPE, "#" + entity.getType());
       }
-      writeProperties(resolvedType, entity.getProperties(), select, json);
+      writeProperties(metadata, resolvedType, entity.getProperties(), select, json);
       writeNavigationProperties(metadata, resolvedType, entity, expand, json);
       json.writeEndObject();
     }
@@ -318,7 +318,8 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
         .getFullQualifiedName().getFullQualifiedNameAsString());
   }
 
-  protected void writeProperties(final EdmStructuredType type, final List<Property> properties,
+  protected void writeProperties(final ServiceMetadata metadata, final EdmStructuredType type,
+      final List<Property> properties,
       final SelectOption select, final JsonGenerator json)
           throws IOException, SerializerException {
     final boolean all = ExpandSelectHelper.isAll(select);
@@ -330,7 +331,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
         final Property property = findProperty(propertyName, properties);
         final Set<List<String>> selectedPaths = all || edmProperty.isPrimitive() ? null :
           ExpandSelectHelper.getSelectedPaths(select.getSelectItems(), propertyName);
-        writeProperty(edmProperty, property, selectedPaths, json);
+        writeProperty(metadata, edmProperty, property, selectedPaths, json);
       }
     }
   }
@@ -382,7 +383,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
     }
   }
 
-  protected void writeProperty(final EdmProperty edmProperty, final Property property,
+  protected void writeProperty(final ServiceMetadata metadata, final EdmProperty edmProperty, final Property property,
       final Set<List<String>> selectedPaths, final JsonGenerator json)
           throws IOException, SerializerException {
     json.writeFieldName(edmProperty.getName());
@@ -399,11 +400,11 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
         }
       }
     } else {
-      writePropertyValue(edmProperty, property, selectedPaths, json);
+      writePropertyValue(metadata, edmProperty, property, selectedPaths, json);
     }
   }
 
-  private void writePropertyValue(final EdmProperty edmProperty,
+  private void writePropertyValue(final ServiceMetadata metadata, final EdmProperty edmProperty,
       final Property property, final Set<List<String>> selectedPaths, final JsonGenerator json)
           throws IOException, SerializerException {
     final EdmType type = edmProperty.getType();
@@ -421,9 +422,10 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
         }
       } else if (property.isComplex()) {
         if (edmProperty.isCollection()) {
-          writeComplexCollection((EdmComplexType) type, property, selectedPaths, json);
+          writeComplexCollection(metadata, (EdmComplexType) type, property, selectedPaths, json);
         } else {
-          writeComplexValue((EdmComplexType) type, property.asComplex().getValue(), selectedPaths, json);
+          writeComplexValue(metadata, property, (EdmComplexType) type, property.asComplex().getValue(), selectedPaths,
+              json);
         }
       } else {
         throw new SerializerException("Property type not yet supported!",
@@ -464,14 +466,15 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
     json.writeEndArray();
   }
 
-  private void writeComplexCollection(final EdmComplexType type, final Property property,
+  private void writeComplexCollection(final ServiceMetadata metadata, final EdmComplexType type,
+      final Property property,
       final Set<List<String>> selectedPaths, final JsonGenerator json)
           throws IOException, SerializerException {
     json.writeStartArray();
     for (Object value : property.asCollection()) {
       switch (property.getValueType()) {
       case COLLECTION_COMPLEX:
-        writeComplexValue(type, ((ComplexValue) value).getValue(), selectedPaths, json);
+        writeComplexValue(metadata, property, type, ((ComplexValue) value).getValue(), selectedPaths, json);
         break;
       default:
         throw new SerializerException("Property type not yet supported!",
@@ -524,14 +527,23 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
     }
   }
 
-  protected void writeComplexValue(final EdmComplexType type, final List<Property> properties,
+  protected void writeComplexValue(final ServiceMetadata metadata, final Property complexProperty,
+      final EdmComplexType type, final List<Property> properties,
       final Set<List<String>> selectedPaths, final JsonGenerator json)
           throws IOException, SerializerException {
     json.writeStartObject();
-    for (final String propertyName : type.getPropertyNames()) {
+
+    final EdmComplexType resolvedType = resolveComplexType(metadata,
+        type, complexProperty.getType());
+    if (!isODataMetadataNone && !resolvedType.equals(type)) {
+      json.writeStringField(Constants.JSON_TYPE,
+          "#" + complexProperty.getType());
+    }
+
+    for (final String propertyName : resolvedType.getPropertyNames()) {
       final Property property = findProperty(propertyName, properties);
       if (selectedPaths == null || ExpandSelectHelper.isSelected(selectedPaths, propertyName)) {
-        writeProperty((EdmProperty) type.getProperty(propertyName), property,
+        writeProperty(metadata, (EdmProperty) resolvedType.getProperty(propertyName), property,
             selectedPaths == null ? null : ExpandSelectHelper.getReducedSelectedPaths(selectedPaths, propertyName),
                 json);
       }
@@ -610,7 +622,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
       }
       final List<Property> values =
           property.isNull() ? Collections.<Property> emptyList() : property.asComplex().getValue();
-          writeProperties(type, values, options == null ? null : options.getSelect(), json);
+          writeProperties(metadata, type, values, options == null ? null : options.getSelect(), json);
           if (!property.isNull() && property.isComplex()) {
             writeNavigationProperties(metadata, type, property.asComplex(),
                 options == null ? null : options.getExpand(), json);
@@ -677,7 +689,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
       writeContextURL(contextURL, json);
       writeMetadataETag(metadata, json);
       json.writeFieldName(Constants.VALUE);
-      writeComplexCollection(type, property, null, json);
+      writeComplexCollection(metadata, type, property, null, json);
       json.writeEndObject();
 
       json.close();

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8468308a/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 52d12e4..0057db4 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
@@ -635,8 +635,8 @@ public class ODataXmlSerializer extends AbstractODataSerializer {
 
   private String derivedComplexType(final EdmComplexType baseType,
       final String definedType) throws SerializerException {
-    String derived = baseType.getFullQualifiedName().getFullQualifiedNameAsString();
-    if (derived.equals(definedType)) {
+    String base = baseType.getFullQualifiedName().getFullQualifiedNameAsString();
+    if (base.equals(definedType)) {
       return null;
     }
     return definedType;
@@ -671,7 +671,7 @@ public class ODataXmlSerializer extends AbstractODataSerializer {
         } else {
           writer.writeAttribute(METADATA, NS_METADATA, Constants.ATTR_TYPE,
               "#" + complexType(metadata, (EdmComplexType) edmProperty.getType(), property.getType()));
-          writeComplexValue(metadata, (EdmComplexType) edmProperty.getType(), property.asComplex().getValue(),
+          writeComplexValue(metadata, property, (EdmComplexType) edmProperty.getType(), property.asComplex().getValue(),
               selectedPaths, writer);
         }
       } else {
@@ -717,7 +717,7 @@ public class ODataXmlSerializer extends AbstractODataSerializer {
       }
       switch (property.getValueType()) {
       case COLLECTION_COMPLEX:
-        writeComplexValue(metadata, type, ((ComplexValue) value).getValue(), selectedPaths, writer);
+        writeComplexValue(metadata, property, type, ((ComplexValue) value).getValue(), selectedPaths, writer);
         break;
       default:
         throw new SerializerException("Property type not yet supported!",
@@ -767,13 +767,17 @@ public class ODataXmlSerializer extends AbstractODataSerializer {
     }
   }
 
-  protected void writeComplexValue(final ServiceMetadata metadata, final EdmComplexType type,
+  protected void writeComplexValue(final ServiceMetadata metadata, Property complexProperty, final EdmComplexType type,
       final List<Property> properties, final Set<List<String>> selectedPaths, final XMLStreamWriter writer)
       throws XMLStreamException, SerializerException {
-    for (final String propertyName : type.getPropertyNames()) {
+
+    final EdmComplexType resolvedType = resolveComplexType(metadata,
+        type, complexProperty.getType());
+    
+    for (final String propertyName : resolvedType.getPropertyNames()) {
       final Property property = findProperty(propertyName, properties);
       if (selectedPaths == null || ExpandSelectHelper.isSelected(selectedPaths, propertyName)) {
-        writeProperty(metadata, (EdmProperty) type.getProperty(propertyName), property,
+        writeProperty(metadata, (EdmProperty) resolvedType.getProperty(propertyName), property,
             selectedPaths == null ? null : ExpandSelectHelper.getReducedSelectedPaths(selectedPaths, propertyName),
             writer);
       }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8468308a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataCreator.java
----------------------------------------------------------------------
diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataCreator.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataCreator.java
index 5c60b38..80a3146 100644
--- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataCreator.java
+++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataCreator.java
@@ -44,6 +44,7 @@ import org.apache.olingo.commons.api.edm.EdmEntityType;
 import org.apache.olingo.server.api.OData;
 import org.apache.olingo.server.api.serializer.SerializerException;
 import org.apache.olingo.server.api.uri.UriHelper;
+import org.apache.olingo.server.tecsvc.provider.ComplexTypeProvider;
 import org.apache.olingo.server.tecsvc.provider.EntityTypeProvider;
 
 public class DataCreator {
@@ -1003,10 +1004,12 @@ public class DataCreator {
 
     entity = new Entity();
     entity.addProperty(createPrimitive("PropertyInt16", (short) 2));
-    entity.addProperty(createComplex("PropertyComp",
-        createComplex("PropertyComp",
+    entity.addProperty(createComplex("PropertyComp", 
+        ComplexTypeProvider.nameCTCompCompExtended.getFullQualifiedNameAsString(), 
+        createComplex("PropertyComp",  
             createPrimitive("PropertyInt16", (short) 987),
-            createPrimitive("PropertyString", "String 2"))));
+            createPrimitive("PropertyString", "String 2")),
+        createPrimitive("PropertyDate", getDateTime(2012, 12, 3, 0, 0, 0))));
     entityCollection.getEntities().add(entity);
 
     setEntityType(entityCollection, edm.getEntityType(EntityTypeProvider.nameETCompComp));
@@ -1174,6 +1177,14 @@ public class DataCreator {
     }
     return new Property(null, name, ValueType.COMPLEX, complexValue);
   }
+  
+  protected static Property createComplex(final String name, final String type, final Property... properties) {
+    ComplexValue complexValue = new ComplexValue();
+    for (final Property property : properties) {
+      complexValue.getValue().add(property);
+    }
+    return new Property(type, name, ValueType.COMPLEX, complexValue);
+  }  
 
   protected static Property createComplexCollection(final String name, final List<Property>... propertiesList) {
     List<ComplexValue> complexCollection = new ArrayList<ComplexValue>();

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8468308a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/ComplexTypeProvider.java
----------------------------------------------------------------------
diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/ComplexTypeProvider.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/ComplexTypeProvider.java
index 502f83a..7d539b6 100644
--- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/ComplexTypeProvider.java
+++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/ComplexTypeProvider.java
@@ -38,6 +38,8 @@ public class ComplexTypeProvider {
   public static final FullQualifiedName nameCTCompCollComp = new FullQualifiedName(SchemaProvider.NAMESPACE,
       "CTCompCollComp");
   public static final FullQualifiedName nameCTCompComp = new FullQualifiedName(SchemaProvider.NAMESPACE, "CTCompComp");
+  public static final FullQualifiedName nameCTCompCompExtended = new FullQualifiedName(
+      SchemaProvider.NAMESPACE, "CTCompCompExtended");
   public static final FullQualifiedName nameCTCompNav = new FullQualifiedName(SchemaProvider.NAMESPACE, "CTCompNav");
 
   public static final FullQualifiedName nameCTMixPrimCollComp = new FullQualifiedName(SchemaProvider.NAMESPACE,
@@ -125,6 +127,12 @@ public class ComplexTypeProvider {
           .setName("CTCompComp")
           .setProperties(Arrays.asList(PropertyProvider.propertyComp_CTTwoPrim));
 
+    } else if (complexTypeName.equals(nameCTCompCompExtended)) {
+      return new CsdlComplexType()
+        .setName("CTCompCompExtended")
+        .setBaseType(nameCTCompComp)
+        .setProperties(Arrays.asList(PropertyProvider.propertyDate));
+      
     } else if (complexTypeName.equals(nameCTCompCollComp)) {
       return new CsdlComplexType()
           .setName("CTCompCollComp")

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8468308a/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 7761b1d..0ad7ac5 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
@@ -560,9 +560,38 @@ public class ODataJsonSerializerTest {
         + "\"@odata.metadataEtag\":\"W/\\\"metadataETag\\\"\","
         + "\"value\":["
         + "{\"PropertyComp\":{\"PropertyComp\":{\"PropertyString\":\"String 1\"}}},"
-        + "{\"PropertyComp\":{\"PropertyComp\":{\"PropertyString\":\"String 2\"}}}]}",
+        + "{\"PropertyComp\":{\"@odata.type\":\"#olingo.odata.test1.CTCompCompExtended\","
+        + "\"PropertyComp\":{\"PropertyString\":\"String 2\"}}}]}",
         resultString);
   }
+  
+  @Test
+  public void selectExtendedComplexType() throws Exception {
+    final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESCompComp");
+    final EdmEntityType entityType = edmEntitySet.getEntityType();
+    final EntityCollection entitySet = data.readAll(edmEntitySet);
+    InputStream result = serializer
+        .entityCollection(metadata, entityType, entitySet,
+            EntityCollectionSerializerOptions.with()
+                .contextURL(ContextURL.with().entitySet(edmEntitySet)
+                    .selectList(helper.buildContextURLSelectList(entityType, null, null))
+                    .build())
+                .build()).getContent();
+    final String resultString = IOUtils.toString(result);
+    
+    String expected = "{" + 
+        "\"@odata.context\":\"$metadata#ESCompComp\"," + 
+        "\"@odata.metadataEtag\":\"W/\\\"metadataETag\\\"\"," + 
+        "\"value\":[" + 
+        "{\"PropertyInt16\":1," +
+        "\"PropertyComp\":{\"PropertyComp\":{" + 
+        "\"PropertyInt16\":123,\"PropertyString\":\"String 1\"}}}," + 
+        "{\"PropertyInt16\":2," + 
+        "\"PropertyComp\":{\"@odata.type\":\"#olingo.odata.test1.CTCompCompExtended\"," + 
+        "\"PropertyComp\":{\"PropertyInt16\":987,\"PropertyString\":\"String 2\"},\"PropertyDate\":\"2012-12-03\"}}]}";
+    Assert.assertEquals(expected, resultString);
+
+  }  
 
   @Test
   public void selectComplexTwice() throws Exception {
@@ -585,7 +614,8 @@ public class ODataJsonSerializerTest {
         + "\"@odata.metadataEtag\":\"W/\\\"metadataETag\\\"\","
         + "\"value\":["
         + "{\"PropertyComp\":{\"PropertyComp\":{\"PropertyInt16\":123,\"PropertyString\":\"String 1\"}}},"
-        + "{\"PropertyComp\":{\"PropertyComp\":{\"PropertyInt16\":987,\"PropertyString\":\"String 2\"}}}]}",
+        + "{\"PropertyComp\":{\"@odata.type\":\"#olingo.odata.test1.CTCompCompExtended\","
+        + "\"PropertyComp\":{\"PropertyInt16\":987,\"PropertyString\":\"String 2\"}}}]}",
         resultString);
   }
 

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8468308a/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/xml/ODataXmlSerializerTest.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/xml/ODataXmlSerializerTest.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/xml/ODataXmlSerializerTest.java
index 9611500..c904ea7 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/xml/ODataXmlSerializerTest.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/xml/ODataXmlSerializerTest.java
@@ -1044,7 +1044,7 @@ public class ODataXmlSerializerTest {
         "      term=\"#olingo.odata.test1.ETCompComp\" />\n" +
         "    <a:content type=\"application/xml\">\n" +
         "      <m:properties>\n" +
-        "        <d:PropertyComp m:type=\"#olingo.odata.test1.CTCompComp\">\n" +
+        "        <d:PropertyComp m:type=\"#olingo.odata.test1.CTCompCompExtended\">\n" +
         "          <d:PropertyComp m:type=\"#olingo.odata.test1.CTTwoPrim\">\n" +
         "            <d:PropertyString>String 2</d:PropertyString>\n" +
         "          </d:PropertyComp>\n" +
@@ -1057,6 +1057,77 @@ public class ODataXmlSerializerTest {
   }
 
   @Test
+  public void selectComplexExtended() throws Exception {
+    final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESCompComp");
+    final EdmEntityType entityType = edmEntitySet.getEntityType();
+    final EntityCollection entitySet = data.readAll(edmEntitySet);
+    long currentTimeMillis = System.currentTimeMillis();
+    InputStream result = serializer
+        .entityCollection(metadata, entityType, entitySet,
+            EntityCollectionSerializerOptions.with()
+                .contextURL(ContextURL.with().entitySet(edmEntitySet)
+                    .selectList(helper.buildContextURLSelectList(entityType, null, null))
+                    .build())
+                .id("http://host/svc/ESCompComp")
+                .build()).getContent();
+    final String resultString = IOUtils.toString(result);
+    String expected = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + 
+        "<a:feed xmlns:a=\"http://www.w3.org/2005/Atom\" xmlns:d=\"http://docs.oasis-open.org/odata/ns/data\" "
+        + "xmlns:m=\"http://docs.oasis-open.org/odata/ns/metadata\" m:context=\"$metadata#ESCompComp\" "
+        + "m:metadata-etag=\"metadataETag\">\n" + 
+        "   <a:id>http://host/svc/ESCompComp</a:id>\n" + 
+        "   <a:entry>\n" + 
+        "      <a:id>ESCompComp(1)</a:id>\n" + 
+        "      <a:title />\n" + 
+        "      <a:summary />\n" + 
+        "      <a:updated>"+ UPDATED_FORMAT.format(new Date(currentTimeMillis)) +"</a:updated>\n" + 
+        "      <a:author>\n" + 
+        "         <a:name />\n" + 
+        "      </a:author>\n" + 
+        "      <a:link rel=\"edit\" href=\"ESCompComp(1)\" />\n" + 
+        "      <a:category scheme=\"http://docs.oasis-open.org/odata/ns/scheme\" "
+        + "term=\"#olingo.odata.test1.ETCompComp\" />\n" + 
+        "      <a:content type=\"application/xml\">\n" + 
+        "         <m:properties>\n" + 
+        "            <d:PropertyInt16 m:type=\"Int16\">1</d:PropertyInt16>\n" + 
+        "            <d:PropertyComp m:type=\"#olingo.odata.test1.CTCompComp\">\n" + 
+        "               <d:PropertyComp m:type=\"#olingo.odata.test1.CTTwoPrim\">\n" + 
+        "                  <d:PropertyInt16 m:type=\"Int16\">123</d:PropertyInt16>\n" + 
+        "                  <d:PropertyString>String 1</d:PropertyString>\n" + 
+        "               </d:PropertyComp>\n" + 
+        "            </d:PropertyComp>\n" + 
+        "         </m:properties>\n" + 
+        "      </a:content>\n" + 
+        "   </a:entry>\n" + 
+        "   <a:entry>\n" + 
+        "      <a:id>ESCompComp(2)</a:id>\n" + 
+        "      <a:title />\n" + 
+        "      <a:summary />\n" + 
+        "      <a:updated>"+ UPDATED_FORMAT.format(new Date(currentTimeMillis)) +"</a:updated>\n" + 
+        "      <a:author>\n" + 
+        "         <a:name />\n" + 
+        "      </a:author>\n" + 
+        "      <a:link rel=\"edit\" href=\"ESCompComp(2)\" />\n" + 
+        "      <a:category scheme=\"http://docs.oasis-open.org/odata/ns/scheme\" "
+        + "term=\"#olingo.odata.test1.ETCompComp\" />\n" + 
+        "      <a:content type=\"application/xml\">\n" + 
+        "         <m:properties>\n" + 
+        "            <d:PropertyInt16 m:type=\"Int16\">2</d:PropertyInt16>\n" + 
+        "            <d:PropertyComp m:type=\"#olingo.odata.test1.CTCompCompExtended\">\n" + 
+        "               <d:PropertyComp m:type=\"#olingo.odata.test1.CTTwoPrim\">\n" + 
+        "                  <d:PropertyInt16 m:type=\"Int16\">987</d:PropertyInt16>\n" + 
+        "                  <d:PropertyString>String 2</d:PropertyString>\n" + 
+        "               </d:PropertyComp>\n" + 
+        "               <d:PropertyDate m:type=\"Date\">2012-12-03</d:PropertyDate>\n" + 
+        "            </d:PropertyComp>\n" + 
+        "         </m:properties>\n" + 
+        "      </a:content>\n" + 
+        "   </a:entry>\n" + 
+        "</a:feed>";
+    checkXMLEqual(expected, resultString);
+  }
+  
+  @Test
   public void selectComplexTwice() throws Exception {
     final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESCompComp");
     final EdmEntityType entityType = edmEntitySet.getEntityType();
@@ -1117,7 +1188,7 @@ public class ODataXmlSerializerTest {
         "      term=\"#olingo.odata.test1.ETCompComp\" />\n" +
         "    <a:content type=\"application/xml\">\n" +
         "      <m:properties>\n" +
-        "        <d:PropertyComp m:type=\"#olingo.odata.test1.CTCompComp\">\n" +
+        "        <d:PropertyComp m:type=\"#olingo.odata.test1.CTCompCompExtended\">\n" +
         "          <d:PropertyComp m:type=\"#olingo.odata.test1.CTTwoPrim\">\n" +
         "            <d:PropertyInt16 m:type=\"Int16\">987</d:PropertyInt16>\n" +
         "            <d:PropertyString>String 2</d:PropertyString>\n" +
@@ -1127,7 +1198,7 @@ public class ODataXmlSerializerTest {
         "    </a:content>\n" +
         "  </a:entry>\n" +
         "</a:feed>\n";
-    checkXMLEqual(expected, resultString);
+    checkXMLEqual(resultString, expected);
   }
 
   @Test


[02/22] olingo-odata4 git commit: OLINGO-864 refining date time behavior

Posted by mi...@apache.org.
OLINGO-864 refining date time behavior

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

Branch: refs/heads/OLINGO-832_StreamSerializerPoC
Commit: 382ec16ee12dda57aa0ab527b45a59cf9b32be54
Parents: fbdf9aa
Author: shawkins <sh...@redhat.com>
Authored: Wed Feb 3 09:46:24 2016 -0500
Committer: shawkins <sh...@redhat.com>
Committed: Wed Feb 3 09:46:24 2016 -0500

----------------------------------------------------------------------
 .../commons/core/edm/primitivetype/EdmDate.java |  5 +-
 .../edm/primitivetype/EdmDateTimeOffset.java    | 67 ++++++++++++++------
 .../core/edm/primitivetype/EdmTimeOfDay.java    | 19 ++----
 .../core/edm/primitivetype/EdmDateTest.java     |  1 -
 .../primitivetype/EdmDateTimeOffsetTest.java    |  4 +-
 .../edm/primitivetype/EdmTimeOfDayTest.java     | 41 +++++++++++-
 6 files changed, 97 insertions(+), 40 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/382ec16e/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDate.java
----------------------------------------------------------------------
diff --git a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDate.java b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDate.java
index 71b747f..fb3f4ad 100644
--- a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDate.java
+++ b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDate.java
@@ -21,7 +21,6 @@ package org.apache.olingo.commons.core.edm.primitivetype;
 import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
 
 import java.util.Calendar;
-import java.util.TimeZone;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -48,7 +47,7 @@ public final class EdmDate extends SingletonPrimitiveType {
       final Boolean isNullable, final Integer maxLength, final Integer precision,
       final Integer scale, final Boolean isUnicode, final Class<T> returnType) throws EdmPrimitiveTypeException {
 
-    final Calendar dateTimeValue = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
+    final Calendar dateTimeValue = Calendar.getInstance(EdmDateTimeOffset.getDefaultTimeZone());
     dateTimeValue.clear();
 
     final Matcher matcher = PATTERN.matcher(value);
@@ -75,7 +74,7 @@ public final class EdmDate extends SingletonPrimitiveType {
       final Boolean isNullable, final Integer maxLength, final Integer precision,
       final Integer scale, final Boolean isUnicode) throws EdmPrimitiveTypeException {
 
-    final Calendar dateTimeValue = EdmDateTimeOffset.createDateTime(value);
+    final Calendar dateTimeValue = EdmDateTimeOffset.createDateTime(value, true);
 
     final StringBuilder result = new StringBuilder(10); // Ten characters are enough for "normal" dates.
     final int year = dateTimeValue.get(Calendar.YEAR);

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/382ec16e/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDateTimeOffset.java
----------------------------------------------------------------------
diff --git a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDateTimeOffset.java b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDateTimeOffset.java
index 6646c83..95b0fa5 100644
--- a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDateTimeOffset.java
+++ b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDateTimeOffset.java
@@ -20,6 +20,7 @@ package org.apache.olingo.commons.core.edm.primitivetype;
 
 import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
 
+import java.sql.Time;
 import java.sql.Timestamp;
 import java.text.DecimalFormat;
 import java.util.Calendar;
@@ -115,6 +116,7 @@ public final class EdmDateTimeOffset extends SingletonPrimitiveType {
 
   /**
    * Converts a {@link Calendar} value into the requested return type if possible.
+   * <br>It is expected that the {@link Calendar} value will already be in the desired time zone.
    *
    * @param dateTimeValue the value
    * @param nanoSeconds nanoseconds part of the value; only used for the {@link Timestamp} return type
@@ -147,6 +149,20 @@ public final class EdmDateTimeOffset extends SingletonPrimitiveType {
       Timestamp timestamp = new Timestamp(dateTimeValue.getTimeInMillis());
       timestamp.setNanos(nanoSeconds);
       return returnType.cast(timestamp);
+    } else if (returnType.isAssignableFrom(Time.class)) {
+      //normalize the value	
+      dateTimeValue.set(Calendar.YEAR, 1970);
+      dateTimeValue.set(Calendar.MONTH, Calendar.JANUARY);
+      dateTimeValue.set(Calendar.DAY_OF_MONTH, 1);
+      dateTimeValue.set(Calendar.MILLISECOND, 0);
+      return returnType.cast(new Time(dateTimeValue.getTimeInMillis())); // may throw IllegalArgumentException
+    } else if (returnType.isAssignableFrom(java.sql.Date.class)) {
+      //normalize the value
+      dateTimeValue.set(Calendar.HOUR_OF_DAY, 0);
+      dateTimeValue.set(Calendar.MINUTE, 0);
+      dateTimeValue.set(Calendar.SECOND, 0);
+      dateTimeValue.set(Calendar.MILLISECOND, 0);
+      return returnType.cast(new java.sql.Date(dateTimeValue.getTimeInMillis())); // may throw IllegalArgumentException
     } else {
       throw new ClassCastException("unsupported return type " + returnType.getSimpleName());
     }
@@ -157,18 +173,8 @@ public final class EdmDateTimeOffset extends SingletonPrimitiveType {
           final Boolean isNullable, final Integer maxLength, final Integer precision,
           final Integer scale, final Boolean isUnicode) throws EdmPrimitiveTypeException {
 
-    final Calendar dateTimeValue;
-    final int fractionalSecs;
-    if (value instanceof Timestamp) {
-      final Calendar tmp = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
-      tmp.setTimeInMillis(((Timestamp) value).getTime());
-      dateTimeValue = createDateTime(tmp);
-      fractionalSecs = ((Timestamp) value).getNanos();
-    } else {
-      dateTimeValue = createDateTime(value);
-      fractionalSecs = dateTimeValue.get(Calendar.MILLISECOND);
-    }
-
+    final Calendar dateTimeValue = createDateTime(value, false);
+    
     final StringBuilder result = new StringBuilder();
     final int year = dateTimeValue.get(Calendar.YEAR);
     appendTwoDigits(result, year / 100);
@@ -186,8 +192,10 @@ public final class EdmDateTimeOffset extends SingletonPrimitiveType {
 
     try {
       if (value instanceof Timestamp) {
+    	int fractionalSecs = ((Timestamp) value).getNanos();
         appendFractionalSeconds(result, fractionalSecs, precision);
       } else {
+        int fractionalSecs = dateTimeValue.get(Calendar.MILLISECOND);
         appendMilliseconds(result, fractionalSecs, precision);
       }
     } catch (final IllegalArgumentException e) {
@@ -211,18 +219,27 @@ public final class EdmDateTimeOffset extends SingletonPrimitiveType {
    * @return the value as {@link Calendar}
    * @throws EdmPrimitiveTypeException if the type of the value is not supported
    */
-  protected static <T> Calendar createDateTime(final T value) throws EdmPrimitiveTypeException {
+  protected static <T> Calendar createDateTime(final T value, boolean isLocal) throws EdmPrimitiveTypeException {
     Calendar dateTimeValue;
     if (value instanceof Date) {
-      // Although java.util.Date, as stated in its documentation,
-      // "is intended to reflect coordinated universal time (UTC)",
-      // its toString() method uses the default time zone. And so do we.
-      dateTimeValue = Calendar.getInstance();
+      TimeZone tz;
+      if (isLocal) {
+        tz = getDefaultTimeZone();
+      } else {
+    	tz = TimeZone.getTimeZone("GMT");  
+      }
+      dateTimeValue = Calendar.getInstance(tz);
       dateTimeValue.setTime((Date) value);
     } else if (value instanceof Calendar) {
       dateTimeValue = (Calendar) ((Calendar) value).clone();
     } else if (value instanceof Long) {
-      dateTimeValue = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
+      TimeZone tz;
+      if (isLocal) {
+        tz = getDefaultTimeZone();
+      } else {
+        tz = TimeZone.getTimeZone("GMT");  
+      }
+      dateTimeValue = Calendar.getInstance(tz);
       dateTimeValue.setTimeInMillis((Long) value);
     } else {
       throw new EdmPrimitiveTypeException("The value type " + value.getClass() + " is not supported.");
@@ -300,4 +317,18 @@ public final class EdmDateTimeOffset extends SingletonPrimitiveType {
       result.append('.').append(formatted.substring(0, actualLength));
     }
   }
+  
+  /**
+   * When the Timezone information is absent on the date time types, like EdmDate, EDMTimeOfDay, EdmDateTimeOffset
+   * this method defines the default timezone that should be used parse and output payload.
+   * User should set system property "defaultTimeZoneForEdmDateTypes" to control this. The default would be
+   * Java VM default if not defined.
+   *   
+   * @return Timezone
+   */
+  protected static TimeZone getDefaultTimeZone() {
+    String tz = System.getProperty("defaultTimeZoneForEdmDateTypes");
+	return (tz != null)?TimeZone.getTimeZone(tz):TimeZone.getDefault();
+  }
+    
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/382ec16e/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmTimeOfDay.java
----------------------------------------------------------------------
diff --git a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmTimeOfDay.java b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmTimeOfDay.java
index fb10e02..3090761 100644
--- a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmTimeOfDay.java
+++ b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmTimeOfDay.java
@@ -22,7 +22,6 @@ import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
 
 import java.sql.Timestamp;
 import java.util.Calendar;
-import java.util.TimeZone;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -52,7 +51,7 @@ public final class EdmTimeOfDay extends SingletonPrimitiveType {
       throw new EdmPrimitiveTypeException("The literal '" + value + "' has illegal content.");
     }
 
-    final Calendar dateTimeValue = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
+    final Calendar dateTimeValue = Calendar.getInstance(EdmDateTimeOffset.getDefaultTimeZone());
     dateTimeValue.clear();
     dateTimeValue.set(Calendar.HOUR_OF_DAY, Byte.parseByte(matcher.group(1)));
     dateTimeValue.set(Calendar.MINUTE, Byte.parseByte(matcher.group(2)));
@@ -92,18 +91,8 @@ public final class EdmTimeOfDay extends SingletonPrimitiveType {
       final Boolean isNullable, final Integer maxLength, final Integer precision,
       final Integer scale, final Boolean isUnicode) throws EdmPrimitiveTypeException {
 
-    final Calendar dateTimeValue;
-    final int fractionalSecs;
-    if (value instanceof Timestamp) {
-      final Calendar tmp = Calendar.getInstance();
-      tmp.setTimeInMillis(((Timestamp) value).getTime());
-      dateTimeValue = EdmDateTimeOffset.createDateTime(tmp);
-      fractionalSecs = ((Timestamp) value).getNanos();
-    } else {
-      dateTimeValue = EdmDateTimeOffset.createDateTime(value);
-      fractionalSecs = dateTimeValue.get(Calendar.MILLISECOND);
-    }
-
+    final Calendar dateTimeValue = EdmDateTimeOffset.createDateTime(value, true);
+    
     final StringBuilder result = new StringBuilder();
     EdmDateTimeOffset.appendTwoDigits(result, dateTimeValue.get(Calendar.HOUR_OF_DAY));
     result.append(':');
@@ -113,8 +102,10 @@ public final class EdmTimeOfDay extends SingletonPrimitiveType {
 
     try {
       if (value instanceof Timestamp) {
+    	int fractionalSecs = ((Timestamp) value).getNanos();
         EdmDateTimeOffset.appendFractionalSeconds(result, fractionalSecs, precision);
       } else {
+        int fractionalSecs = dateTimeValue.get(Calendar.MILLISECOND);
         EdmDateTimeOffset.appendMilliseconds(result, fractionalSecs, precision);
       }
     } catch (final IllegalArgumentException e) {

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/382ec16e/lib/commons-core/src/test/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDateTest.java
----------------------------------------------------------------------
diff --git a/lib/commons-core/src/test/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDateTest.java b/lib/commons-core/src/test/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDateTest.java
index 6e10d2b..26b6a49 100644
--- a/lib/commons-core/src/test/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDateTest.java
+++ b/lib/commons-core/src/test/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDateTest.java
@@ -67,7 +67,6 @@ public class EdmDateTest extends PrimitiveTypeBaseTest {
   public void valueOfString() throws Exception {
     Calendar dateTime = Calendar.getInstance();
     dateTime.clear();
-    dateTime.setTimeZone(TimeZone.getTimeZone("GMT"));
     dateTime.set(2012, 1, 29);
     assertEquals(dateTime, instance.valueOfString("2012-02-29", null, null, null, null, null, Calendar.class));
     assertEquals(Long.valueOf(dateTime.getTimeInMillis()), instance.valueOfString("2012-02-29", null, null, null, null,

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/382ec16e/lib/commons-core/src/test/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDateTimeOffsetTest.java
----------------------------------------------------------------------
diff --git a/lib/commons-core/src/test/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDateTimeOffsetTest.java b/lib/commons-core/src/test/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDateTimeOffsetTest.java
index 3013916..0b51925 100644
--- a/lib/commons-core/src/test/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDateTimeOffsetTest.java
+++ b/lib/commons-core/src/test/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDateTimeOffsetTest.java
@@ -28,7 +28,6 @@ import java.util.Date;
 import java.util.TimeZone;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
 
 public class EdmDateTimeOffsetTest extends PrimitiveTypeBaseTest {
 
@@ -77,8 +76,7 @@ public class EdmDateTimeOffsetTest extends PrimitiveTypeBaseTest {
     assertEquals("1969-12-31T23:59:59.98Z", instance.valueToString(-20L, null, null, 2, null, null));
 
     final Date date = new Date(millis);
-    final String time = date.toString().substring(11, 19);
-    assertTrue(instance.valueToString(date, null, null, 3, null, null).contains(time));
+    assertEquals("2012-02-29T23:32:03.007Z", instance.valueToString(date, null, null, 3, null, null));
 
     expectFacetsErrorInValueToString(instance, millis, null, null, null, null, null);
     expectFacetsErrorInValueToString(instance, 3L, null, null, 2, null, null);

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/382ec16e/lib/commons-core/src/test/java/org/apache/olingo/commons/core/edm/primitivetype/EdmTimeOfDayTest.java
----------------------------------------------------------------------
diff --git a/lib/commons-core/src/test/java/org/apache/olingo/commons/core/edm/primitivetype/EdmTimeOfDayTest.java b/lib/commons-core/src/test/java/org/apache/olingo/commons/core/edm/primitivetype/EdmTimeOfDayTest.java
index 917814d..57dd5d9 100644
--- a/lib/commons-core/src/test/java/org/apache/olingo/commons/core/edm/primitivetype/EdmTimeOfDayTest.java
+++ b/lib/commons-core/src/test/java/org/apache/olingo/commons/core/edm/primitivetype/EdmTimeOfDayTest.java
@@ -22,6 +22,7 @@ import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
 import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
 import org.junit.Test;
 
+import java.sql.Time;
 import java.util.Calendar;
 import java.util.TimeZone;
 
@@ -60,12 +61,50 @@ public class EdmTimeOfDayTest extends PrimitiveTypeBaseTest {
 
     expectTypeErrorInValueToString(instance, 0);
   }
+  
+  @Test
+  public void valueToStringWithGMT() throws Exception {
+    Calendar dateTime = Calendar.getInstance();
+    dateTime.clear();
+    dateTime.setTimeZone(TimeZone.getTimeZone("GMT+11:30"));
+    dateTime.set(1, 2, 3, 4, 5, 6);
+    assertEquals("04:05:06", instance.valueToString(dateTime, null, null, null, null, null));
+  }
+  
+  @Test
+  public void testRoundTripTime() throws Exception {
+      java.sql.Time time = instance.valueOfString("04:05:06.002", true,
+                4000, 3, 0, true, java.sql.Time.class);
+      String val = instance.valueToString(time, true, 4000, 3, 0, true);
+      assertEquals("04:05:06", val);  
+  } 
+  
+  @Test
+  public void toTimeObject() throws Exception {
+    Calendar dateTime = Calendar.getInstance();
+    dateTime.clear();
+    dateTime.set(Calendar.HOUR, 12);
+    
+    Time timeValue = instance.valueOfString("12:00:00", null, null, null, null, null, Time.class);
+    assertEquals(dateTime.getTimeInMillis(), timeValue.getTime());
+  }
+  
+  @Test
+  public void fromTimeObject() throws Exception {
+    Calendar dateTime = Calendar.getInstance();
+    dateTime.clear();
+    dateTime.set(Calendar.HOUR, 5);
+    dateTime.set(Calendar.MINUTE, 59);
+    dateTime.set(Calendar.SECOND, 23);
+    
+    Time time = new Time(dateTime.getTimeInMillis());
+    assertEquals("05:59:23", instance.valueToString(time, null, null, null, null, null));
+  }
 
   @Test
   public void valueOfString() throws Exception {
     Calendar dateTime = Calendar.getInstance();
     dateTime.clear();
-    dateTime.setTimeZone(TimeZone.getTimeZone("GMT"));
 
     assertEquals(dateTime, instance.valueOfString("00:00", null, null, null, null, null, Calendar.class));
     assertEquals(dateTime, instance.valueOfString("00:00:00", null, null, null, null, null, Calendar.class));


[07/22] olingo-odata4 git commit: [OLINGO-852] less warnings + general clean-up

Posted by mi...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/fit/src/main/java/org/apache/olingo/fit/Vocabularies.java
----------------------------------------------------------------------
diff --git a/fit/src/main/java/org/apache/olingo/fit/Vocabularies.java b/fit/src/main/java/org/apache/olingo/fit/Vocabularies.java
index 0390eae..c13bf35 100644
--- a/fit/src/main/java/org/apache/olingo/fit/Vocabularies.java
+++ b/fit/src/main/java/org/apache/olingo/fit/Vocabularies.java
@@ -27,7 +27,6 @@ import javax.ws.rs.Produces;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 
-import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion;
 import org.apache.olingo.fit.metadata.Metadata;
 import org.apache.olingo.fit.utils.Accept;
 import org.apache.olingo.fit.utils.ConstantKey;
@@ -43,8 +42,8 @@ public class Vocabularies {
   private final XMLUtilities xml;
 
   public Vocabularies() throws IOException {
-    Metadata metadata = new Metadata(FSManager.instance(ODataServiceVersion.V40).readRes(
-            "vocabularies-" + Constants.get(ConstantKey.METADATA), Accept.XML));
+    Metadata metadata = new Metadata(FSManager.instance()
+        .readRes("vocabularies-" + Constants.get(ConstantKey.METADATA), Accept.XML));
     xml = new XMLUtilities(metadata);
   }
 
@@ -55,8 +54,7 @@ public class Vocabularies {
     try {
       return xml.createResponse(
           null,
-          FSManager.instance(ODataServiceVersion.V40).readRes(
-              "vocabularies-" + Constants.get(ConstantKey.METADATA), Accept.XML),
+          FSManager.instance().readRes("vocabularies-" + Constants.get(ConstantKey.METADATA), Accept.XML),
               null,
               Accept.XML);
     } catch (Exception e) {
@@ -71,7 +69,7 @@ public class Vocabularies {
     try {
       return xml.createResponse(
           null,
-          FSManager.instance(ODataServiceVersion.V40).readFile(vocabulary, null),
+          FSManager.instance().readFile(vocabulary, null),
           null,
           Accept.XML);
     } catch (Exception e) {

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/fit/src/main/java/org/apache/olingo/fit/metadata/EntitySet.java
----------------------------------------------------------------------
diff --git a/fit/src/main/java/org/apache/olingo/fit/metadata/EntitySet.java b/fit/src/main/java/org/apache/olingo/fit/metadata/EntitySet.java
index 15285d2..c165bb7 100644
--- a/fit/src/main/java/org/apache/olingo/fit/metadata/EntitySet.java
+++ b/fit/src/main/java/org/apache/olingo/fit/metadata/EntitySet.java
@@ -24,18 +24,10 @@ import java.util.Map;
 public class EntitySet extends AbstractMetadataElement {
 
   private final String name;
-
   private String type;
-
   private final boolean singleton;
-
-  // --------------------------
-  // V4 only
-  // --------------------------
   private final Map<String, String> binding;
 
-  // --------------------------
-
   public EntitySet(final String name, final boolean singleton) {
     this.name = name;
     this.singleton = singleton;

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/fit/src/main/java/org/apache/olingo/fit/rest/OAuth2RequestFilter.java
----------------------------------------------------------------------
diff --git a/fit/src/main/java/org/apache/olingo/fit/rest/OAuth2RequestFilter.java b/fit/src/main/java/org/apache/olingo/fit/rest/OAuth2RequestFilter.java
index 17476dd..a7ab945 100644
--- a/fit/src/main/java/org/apache/olingo/fit/rest/OAuth2RequestFilter.java
+++ b/fit/src/main/java/org/apache/olingo/fit/rest/OAuth2RequestFilter.java
@@ -19,14 +19,13 @@
 package org.apache.olingo.fit.rest;
 
 import javax.ws.rs.container.ContainerRequestContext;
-import javax.ws.rs.container.ContainerRequestFilter;
 import javax.ws.rs.ext.Provider;
 
 import org.apache.commons.lang3.StringUtils;
 import org.apache.cxf.rs.security.oauth2.filters.OAuthRequestFilter;
 
 @Provider
-public class OAuth2RequestFilter extends OAuthRequestFilter implements ContainerRequestFilter {
+public class OAuth2RequestFilter extends OAuthRequestFilter {
 
   @Override
   public void filter(final ContainerRequestContext context) {

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/fit/src/main/java/org/apache/olingo/fit/serializer/FITAtomDeserializer.java
----------------------------------------------------------------------
diff --git a/fit/src/main/java/org/apache/olingo/fit/serializer/FITAtomDeserializer.java b/fit/src/main/java/org/apache/olingo/fit/serializer/FITAtomDeserializer.java
index d02475d..357dc5a 100644
--- a/fit/src/main/java/org/apache/olingo/fit/serializer/FITAtomDeserializer.java
+++ b/fit/src/main/java/org/apache/olingo/fit/serializer/FITAtomDeserializer.java
@@ -21,7 +21,6 @@ package org.apache.olingo.fit.serializer;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.nio.charset.Charset;
-import java.nio.charset.CharsetDecoder;
 import java.nio.charset.CodingErrorAction;
 
 import javax.xml.stream.XMLEventReader;
@@ -32,19 +31,15 @@ import org.apache.olingo.commons.api.Constants;
 
 public class FITAtomDeserializer extends AtomDeserializer {
 
-  private static final Charset ENCODING = Charset.forName(Constants.UTF8);
-
   public FITAtomDeserializer() {
     super();
   }
 
   @Override
   protected XMLEventReader getReader(final InputStream input) throws XMLStreamException {
-    final CharsetDecoder decoder = ENCODING.newDecoder();
-    decoder.onMalformedInput(CodingErrorAction.IGNORE);
-    decoder.onUnmappableCharacter(CodingErrorAction.IGNORE);
-
-    return FACTORY.createXMLEventReader(new InputStreamReader(input, decoder));
+    return FACTORY.createXMLEventReader(new InputStreamReader(input,
+        Charset.forName(Constants.UTF8).newDecoder()
+            .onMalformedInput(CodingErrorAction.IGNORE)
+            .onUnmappableCharacter(CodingErrorAction.IGNORE)));
   }
-
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/fit/src/main/java/org/apache/olingo/fit/utils/AbstractUtilities.java
----------------------------------------------------------------------
diff --git a/fit/src/main/java/org/apache/olingo/fit/utils/AbstractUtilities.java b/fit/src/main/java/org/apache/olingo/fit/utils/AbstractUtilities.java
index ee87eb0..a14cb8b 100644
--- a/fit/src/main/java/org/apache/olingo/fit/utils/AbstractUtilities.java
+++ b/fit/src/main/java/org/apache/olingo/fit/utils/AbstractUtilities.java
@@ -34,7 +34,6 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.UUID;
-import java.util.regex.Pattern;
 
 import javax.ws.rs.NotFoundException;
 import javax.ws.rs.core.Response;
@@ -70,38 +69,19 @@ public abstract class AbstractUtilities {
    */
   protected static final Logger LOG = LoggerFactory.getLogger(AbstractUtilities.class);
 
-  protected static final Pattern ENTITY_URI_PATTERN = Pattern.compile(".*\\/.*\\(.*\\)");
-
-  /**
-   * Batch/Changeset content type.
-   */
-  public static final String MULTIPART_CONTENT_TYPE = "multipart/mixed";
-
-  /**
-   * Batch item content type.
-   */
-  public static final String ITEM_CONTENT_TYPE = "application/http";
-
-  /**
-   * Boundary key.
-   */
-  public static final String BOUNDARY = "boundary";
-
   protected final Metadata metadata;
 
   protected final FSManager fsManager;
 
   protected final ODataDeserializer atomDeserializer;
-
   protected final ODataDeserializer jsonDeserializer;
 
   protected final ODataSerializer atomSerializer;
-
   protected final ODataSerializer jsonSerializer;
 
   public AbstractUtilities(final Metadata metadata) throws IOException {
     this.metadata = metadata;
-    fsManager = FSManager.instance(ODataServiceVersion.V40);
+    fsManager = FSManager.instance();
     atomDeserializer = new FITAtomDeserializer();
     jsonDeserializer = new JsonDeserializer(true);
     atomSerializer = new AtomSerializer(true);

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/fit/src/main/java/org/apache/olingo/fit/utils/Accept.java
----------------------------------------------------------------------
diff --git a/fit/src/main/java/org/apache/olingo/fit/utils/Accept.java b/fit/src/main/java/org/apache/olingo/fit/utils/Accept.java
index 5f9a724..9acda31 100644
--- a/fit/src/main/java/org/apache/olingo/fit/utils/Accept.java
+++ b/fit/src/main/java/org/apache/olingo/fit/utils/Accept.java
@@ -20,33 +20,31 @@ package org.apache.olingo.fit.utils;
 
 import java.util.regex.Pattern;
 
-import org.apache.commons.lang3.StringUtils;
-import org.apache.http.entity.ContentType;
+import org.apache.olingo.commons.api.format.ContentType;
 import org.apache.olingo.fit.UnsupportedMediaTypeException;
 
 public enum Accept {
 
-  TEXT(ContentType.TEXT_PLAIN.getMimeType(), ".txt"),
-  XML(ContentType.APPLICATION_XML.getMimeType(), ".xml"),
-  ATOM(ContentType.APPLICATION_ATOM_XML.getMimeType(), ".xml"),
-  JSON(ContentType.APPLICATION_JSON.getMimeType() + ";odata.metadata=minimal", ".full.json"),
-  JSON_NOMETA(ContentType.APPLICATION_JSON.getMimeType() + ";odata.metadata=none", ".full.json"),
-  JSON_FULLMETA(ContentType.APPLICATION_JSON.getMimeType() + ";odata.metadata=full", ".full.json");
+  TEXT(ContentType.TEXT_PLAIN, ".txt"),
+  XML(ContentType.APPLICATION_XML, ".xml"),
+  ATOM(ContentType.APPLICATION_ATOM_XML, ".xml"),
+  JSON(ContentType.JSON, ".full.json"),
+  JSON_NOMETA(ContentType.JSON_NO_METADATA, ".full.json"),
+  JSON_FULLMETA(ContentType.JSON_FULL_METADATA, ".full.json");
 
-  private final String contentTypeV4;
+  private static Pattern allTypesPattern = Pattern.compile("(.*,)?\\*/\\*([,;].*)?");
 
+  private final ContentType contentType;
   private final String fileExtension;
 
-  private static Pattern allTypesPattern = Pattern.compile("(.*,)?\\*/\\*([,;].*)?");
-
-  Accept(final String contentTypeV4, final String fileExtension) {
-    this.contentTypeV4 = contentTypeV4;
+  Accept(final ContentType contentType, final String fileExtension) {
+    this.contentType = contentType;
     this.fileExtension = fileExtension;
   }
 
   @Override
   public String toString() {
-    return contentTypeV4;
+    return contentType.toContentTypeString();
   }
 
   public String getExtension() {
@@ -58,15 +56,14 @@ public enum Accept {
   }
 
   public static Accept parse(final String contentType, final Accept def) {
-    if (StringUtils.isBlank(contentType) || allTypesPattern.matcher(contentType).matches()) {
+    if (contentType == null || contentType.isEmpty() || allTypesPattern.matcher(contentType).matches()) {
       return def;
     } else if (contentType.startsWith(JSON_NOMETA.toString())) {
       return JSON_NOMETA;
     } else if (contentType.startsWith(JSON_FULLMETA.toString())) {
       return JSON_FULLMETA;
     } else if (contentType.startsWith(JSON.toString())
-        || contentType.startsWith(ContentType.APPLICATION_JSON.getMimeType())) {
-
+        || contentType.startsWith(ContentType.APPLICATION_JSON.toContentTypeString())) {
       return JSON;
     } else if (contentType.startsWith(XML.toString())) {
       return XML;

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/fit/src/main/java/org/apache/olingo/fit/utils/Commons.java
----------------------------------------------------------------------
diff --git a/fit/src/main/java/org/apache/olingo/fit/utils/Commons.java b/fit/src/main/java/org/apache/olingo/fit/utils/Commons.java
index 32644d9..5ee4d25 100644
--- a/fit/src/main/java/org/apache/olingo/fit/utils/Commons.java
+++ b/fit/src/main/java/org/apache/olingo/fit/utils/Commons.java
@@ -27,7 +27,6 @@ import java.net.URI;
 import java.util.AbstractMap.SimpleEntry;
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.EnumMap;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
@@ -40,7 +39,6 @@ import org.apache.commons.lang3.tuple.Pair;
 import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
 import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion;
 import org.apache.olingo.fit.metadata.Metadata;
-import org.codehaus.plexus.util.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -59,9 +57,6 @@ public abstract class Commons {
    */
   protected static final Logger LOG = LoggerFactory.getLogger(Commons.class);
 
-  private static final EnumMap<ODataServiceVersion, Metadata> METADATA =
-      new EnumMap<ODataServiceVersion, Metadata>(ODataServiceVersion.class);
-
   protected static final Pattern MULTIKEY_PATTERN = Pattern.compile("(.*=.*,?)+");
 
   protected static final Map<String, Integer> SEQUENCE = new HashMap<String, Integer>();
@@ -99,14 +94,11 @@ public abstract class Commons {
         new ImmutablePair<String, EdmPrimitiveTypeKind>("ID", EdmPrimitiveTypeKind.Guid));
   }
 
-  public static Metadata getMetadata(final ODataServiceVersion version) {
-    if (!METADATA.containsKey(version)) {
-      final InputStream is = Commons.class.getResourceAsStream("/" + version.name() + "/metadata.xml");
-
-      METADATA.put(version, new Metadata(is));
-    }
+  private static final Metadata METADATA =
+      new Metadata(Commons.class.getResourceAsStream("/" + ODataServiceVersion.V40.name() + "/metadata.xml"));
 
-    return METADATA.get(version);
+  public static Metadata getMetadata() {
+    return METADATA;
   }
 
   public static Map<String, Pair<String, EdmPrimitiveTypeKind>> getMediaContent() {
@@ -115,13 +107,13 @@ public abstract class Commons {
 
   public static String getEntityURI(final String entitySetName, final String entityKey) {
     // expected singleton in case of null key
-    return entitySetName + (StringUtils.isNotBlank(entityKey) ? "(" + entityKey + ")" : "");
+    return entitySetName + (entityKey == null || entityKey.isEmpty() ? "" : "(" + entityKey + ")");
   }
 
   public static String getEntityBasePath(final String entitySetName, final String entityKey) {
     // expected singleton in case of null key
     return entitySetName + File.separatorChar
-        + (StringUtils.isNotBlank(entityKey) ? getEntityKey(entityKey) + File.separatorChar : "");
+        + (entityKey == null || entityKey.isEmpty() ? "" : getEntityKey(entityKey) + File.separatorChar);
   }
 
   public static String getLinksURI(final String entitySetName, final String entityId, final String linkName)
@@ -138,7 +130,7 @@ public abstract class Commons {
   public static String getLinksPath(final String basePath, final String linkName, final Accept accept)
       throws IOException {
     try {
-      return FSManager.instance(ODataServiceVersion.V40)
+      return FSManager.instance()
           .getAbsolutePath(basePath + Constants.get(ConstantKey.LINKS_FILE_PATH)
               + File.separatorChar + linkName, accept);
     } catch (Exception e) {
@@ -281,7 +273,7 @@ public abstract class Commons {
 
   public static String getETag(final String basePath) throws Exception {
     try {
-      final InputStream is = FSManager.instance(ODataServiceVersion.V40).readFile(basePath + "etag", Accept.TEXT);
+      final InputStream is = FSManager.instance().readFile(basePath + "etag", Accept.TEXT);
       if (is.available() <= 0) {
         return null;
       } else {

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/fit/src/main/java/org/apache/olingo/fit/utils/ConstantKey.java
----------------------------------------------------------------------
diff --git a/fit/src/main/java/org/apache/olingo/fit/utils/ConstantKey.java b/fit/src/main/java/org/apache/olingo/fit/utils/ConstantKey.java
index 7315652..a8425df 100644
--- a/fit/src/main/java/org/apache/olingo/fit/utils/ConstantKey.java
+++ b/fit/src/main/java/org/apache/olingo/fit/utils/ConstantKey.java
@@ -25,20 +25,13 @@ public enum ConstantKey {
   ODATA_COUNT_NAME,
   ODATA_METADATA_PREFIX,
   ODATA_METADATA_ENTITY_SUFFIX,
-  ATOM_DEF_TYPE,
   ATOM_PROPERTY_PREFIX,
-  ATOM_METADATA_PREFIX,
-  ATOM_METADATA_NS,
-  ATOM_DATASERVICE_NS,
   ATOM_LINK_ENTRY,
   ATOM_LINK_FEED,
   ATOM_LINK_REL,
-  TYPE,
   INLINE_LOCAL,
-  INLINE_FILE_PATH,
   LINKS_FILE_PATH,
   INLINE,
-  CONTENT,
   PROPERTIES,
   LINK,
   DATASERVICES_NS,
@@ -66,6 +59,5 @@ public enum ConstantKey {
   JSON_TYPE_SUFFIX,
   JSON_ID_NAME,
   JSON_EDITLINK_NAME,
-  XHTTP_HEADER_NAME;
-
+  XHTTP_HEADER_NAME
 };

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/fit/src/main/java/org/apache/olingo/fit/utils/Constants.java
----------------------------------------------------------------------
diff --git a/fit/src/main/java/org/apache/olingo/fit/utils/Constants.java b/fit/src/main/java/org/apache/olingo/fit/utils/Constants.java
index d0915a4..6a1d16a 100644
--- a/fit/src/main/java/org/apache/olingo/fit/utils/Constants.java
+++ b/fit/src/main/java/org/apache/olingo/fit/utils/Constants.java
@@ -55,19 +55,12 @@ public class Constants {
         "http://localhost:9080/stub/StaticService/V40/Static.svc/$metadata#");
     constants.put(ConstantKey.ODATA_METADATA_ENTITY_SUFFIX, "/$entity");
     constants.put(ConstantKey.ODATA_COUNT_NAME, "odata.count");
-    constants.put(ConstantKey.ATOM_DEF_TYPE, "Edm.String");
     constants.put(ConstantKey.ATOM_PROPERTY_PREFIX, "d:");
-    constants.put(ConstantKey.ATOM_METADATA_PREFIX, "m:");
-    constants.put(ConstantKey.ATOM_METADATA_NS, "xmlns:m");
-    constants.put(ConstantKey.ATOM_DATASERVICE_NS, "xmlns:d");
     constants.put(ConstantKey.ATOM_LINK_ENTRY, "application/atom+xml;type=entry");
     constants.put(ConstantKey.ATOM_LINK_FEED, "application/atom+xml;type=feed");
-    constants.put(ConstantKey.TYPE, "m:type");
     constants.put(ConstantKey.INLINE_LOCAL, "inline");
-    constants.put(ConstantKey.INLINE_FILE_PATH, "inline");
     constants.put(ConstantKey.LINKS_FILE_PATH, "links");
     constants.put(ConstantKey.INLINE, "m:inline");
-    constants.put(ConstantKey.CONTENT, "content");
     constants.put(ConstantKey.PROPERTIES, "m:properties");
     constants.put(ConstantKey.LINK, "link");
     constants.put(ConstantKey.METADATA, "metadata");

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/fit/src/main/java/org/apache/olingo/fit/utils/FSManager.java
----------------------------------------------------------------------
diff --git a/fit/src/main/java/org/apache/olingo/fit/utils/FSManager.java b/fit/src/main/java/org/apache/olingo/fit/utils/FSManager.java
index d3530c8..8202619 100644
--- a/fit/src/main/java/org/apache/olingo/fit/utils/FSManager.java
+++ b/fit/src/main/java/org/apache/olingo/fit/utils/FSManager.java
@@ -25,8 +25,6 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.OutputStreamWriter;
-import java.util.EnumMap;
-import java.util.Map;
 
 import javax.ws.rs.NotFoundException;
 
@@ -61,37 +59,34 @@ public class FSManager {
 
   private final FileSystemManager fsManager;
 
-  private static Map<ODataServiceVersion, FSManager> instance =
-      new EnumMap<ODataServiceVersion, FSManager>(ODataServiceVersion.class);
+  private static FSManager instance = null;
 
-  private final ODataServiceVersion version;
-
-  public static FSManager instance(final ODataServiceVersion version) throws IOException {
-    if (!instance.containsKey(version)) {
-      instance.put(version, new FSManager(version));
+  public static FSManager instance() throws IOException {
+    if (instance == null) {
+      instance = new FSManager();
     }
-    return instance.get(version);
+    return instance;
   }
 
-  private FSManager(final ODataServiceVersion version) throws IOException {
-    this.version = version;
+  private FSManager() throws IOException {
     fsManager = VFS.getManager();
 
-    final FileObject basePath = fsManager.resolveFile(RES_PREFIX + File.separatorChar + version.name());
+    final FileObject basePath =
+        fsManager.resolveFile(RES_PREFIX + File.separatorChar + ODataServiceVersion.V40.name());
     final String absoluteBaseFolder = basePath.getURL().getPath();
 
     for (FileObject fo : find(basePath, null)) {
       if (fo.getType() == FileType.FILE
           && !fo.getName().getBaseName().contains("Metadata")
           && !fo.getName().getBaseName().contains("metadata")) {
-        final String path = fo.getURL().getPath().replace(absoluteBaseFolder, "//" + version.name());
+        final String path = fo.getURL().getPath().replace(absoluteBaseFolder, "//" + ODataServiceVersion.V40.name());
         putInMemory(fo.getContent().getInputStream(), path);
       }
     }
   }
 
   public String getAbsolutePath(final String relativePath, final Accept accept) {
-    return File.separatorChar + version.name() + File.separatorChar + relativePath
+    return File.separatorChar + ODataServiceVersion.V40.name() + File.separatorChar + relativePath
         + (accept == null ? "" : accept.getExtension());
   }
 

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/fit/src/main/java/org/apache/olingo/fit/utils/InjectableSerializerProvider.java
----------------------------------------------------------------------
diff --git a/fit/src/main/java/org/apache/olingo/fit/utils/InjectableSerializerProvider.java b/fit/src/main/java/org/apache/olingo/fit/utils/InjectableSerializerProvider.java
deleted file mode 100644
index 02ada09..0000000
--- a/fit/src/main/java/org/apache/olingo/fit/utils/InjectableSerializerProvider.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * 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.utils;
-
-import com.fasterxml.jackson.databind.SerializationConfig;
-import com.fasterxml.jackson.databind.SerializerProvider;
-import com.fasterxml.jackson.databind.ser.DefaultSerializerProvider;
-import com.fasterxml.jackson.databind.ser.SerializerFactory;
-
-public class InjectableSerializerProvider extends DefaultSerializerProvider {
-
-  private static final long serialVersionUID = 3432260063063739646L;
-
-  public InjectableSerializerProvider(
-      final SerializerProvider src, final SerializationConfig config, final SerializerFactory factory) {
-
-    super(src, config, factory);
-  }
-
-  @Override
-  public InjectableSerializerProvider createInstance(
-      final SerializationConfig config, final SerializerFactory factory) {
-
-    return this;
-  }
-}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/fit/src/main/java/org/apache/olingo/fit/utils/JSONUtilities.java
----------------------------------------------------------------------
diff --git a/fit/src/main/java/org/apache/olingo/fit/utils/JSONUtilities.java b/fit/src/main/java/org/apache/olingo/fit/utils/JSONUtilities.java
index 8be6b11..b18886d 100644
--- a/fit/src/main/java/org/apache/olingo/fit/utils/JSONUtilities.java
+++ b/fit/src/main/java/org/apache/olingo/fit/utils/JSONUtilities.java
@@ -39,7 +39,6 @@ import org.apache.olingo.fit.metadata.Metadata;
 import org.apache.olingo.fit.metadata.NavigationProperty;
 
 import com.fasterxml.jackson.annotation.JsonInclude;
-import com.fasterxml.jackson.databind.InjectableValues;
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.node.ArrayNode;
@@ -48,21 +47,10 @@ import com.fasterxml.jackson.databind.node.TextNode;
 
 public class JSONUtilities extends AbstractUtilities {
 
-  private final ObjectMapper mapper;
+  private final ObjectMapper mapper = new ObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_NULL);
 
   public JSONUtilities(final Metadata metadata) throws IOException {
     super(metadata);
-
-    mapper = new ObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_NULL);
-    mapper.setInjectableValues(new InjectableValues.Std().
-        addValue(Boolean.class, Boolean.TRUE));
-    // addValue(ODataServiceVersion.class, version))
-
-    mapper.setSerializerProvider(new InjectableSerializerProvider(mapper.getSerializerProvider(),
-        mapper.getSerializationConfig().
-        // withAttribute(ODataServiceVersion.class, version).
-        withAttribute(Boolean.class, Boolean.TRUE),
-        mapper.getSerializerFactory()));
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/fit/src/main/java/org/apache/olingo/fit/utils/MetadataLinkInfo.java
----------------------------------------------------------------------
diff --git a/fit/src/main/java/org/apache/olingo/fit/utils/MetadataLinkInfo.java b/fit/src/main/java/org/apache/olingo/fit/utils/MetadataLinkInfo.java
deleted file mode 100644
index e79ce96..0000000
--- a/fit/src/main/java/org/apache/olingo/fit/utils/MetadataLinkInfo.java
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * 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.utils;
-
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-import javax.ws.rs.NotFoundException;
-
-public class MetadataLinkInfo {
-
-  private Map<String, EntitySet> entitySets = new HashMap<String, EntitySet>();
-
-  public void setSingleton(final String entitySetName) {
-    entitySets.get(entitySetName).setSingleton(true);
-  }
-
-  public boolean isSingleton(final String entitySetName) {
-    return entitySets.get(entitySetName).isSingleton();
-  }
-
-  public Set<String> getEntitySets() {
-    return entitySets.keySet();
-  }
-
-  public void addEntitySet(final String entitySetName) {
-    if (!entitySets.containsKey(entitySetName)) {
-      entitySets.put(entitySetName, new EntitySet(entitySetName));
-    }
-  }
-
-  public void addLink(
-      final String entitySetName, final String linkName, final String targetName, final boolean isFeed) {
-    final EntitySet entitySet;
-    if (entitySets.containsKey(entitySetName)) {
-      entitySet = entitySets.get(entitySetName);
-    } else {
-      entitySet = new EntitySet(entitySetName);
-      entitySets.put(entitySetName, entitySet);
-    }
-
-    entitySet.add(linkName, targetName, isFeed);
-  }
-
-  public Set<String> getNavigationLinkNames(final String entitySetName) {
-    final Set<String> res = new HashSet<String>();
-
-    if (!entitySets.containsKey(entitySetName)) {
-      throw new NotFoundException();
-    }
-
-    for (NavigationLink navigationLink : entitySets.get(entitySetName).getLinks()) {
-      res.add(navigationLink.getName());
-    }
-
-    return res;
-  }
-
-  public boolean exists(final String entitySetName, final String linkName) {
-    try {
-      return getNavigationLinkNames(entitySetName).contains(linkName);
-    } catch (Exception e) {
-      return false;
-    }
-  }
-
-  public boolean isFeed(final String entitySetName, final String linkName) {
-    return entitySets.containsKey(entitySetName) && entitySets.get(entitySetName).isFeed(linkName);
-  }
-
-  public String getTargetName(final String entitySetName, final String linkName) {
-    if (!entitySets.containsKey(entitySetName)) {
-      throw new NotFoundException();
-    }
-
-    final String targetName = entitySets.get(entitySetName).getLink(linkName).getTargetName();
-    return targetName.substring(targetName.lastIndexOf(".") + 1);
-  }
-
-  private static class EntitySet {
-
-    private String name;
-
-    private Set<NavigationLink> links;
-
-    private boolean singleton;
-
-    public EntitySet(final String name) {
-      this.name = name;
-      links = new HashSet<NavigationLink>();
-    }
-
-    public void add(final String linkName, final String targetName, final boolean isFeed) {
-      links.add(new NavigationLink(linkName, targetName, isFeed));
-    }
-
-    public Set<NavigationLink> getLinks() {
-      return links;
-    }
-
-    public NavigationLink getLink(final String linkName) {
-      for (NavigationLink navigationLink : links) {
-        if (linkName.equalsIgnoreCase(navigationLink.getName())) {
-          return navigationLink;
-        }
-      }
-
-      throw new NotFoundException();
-    }
-
-    public boolean isFeed(final String linkName) {
-      try {
-        return getLink(linkName).isFeed();
-      } catch (Exception e) {
-        return false;
-      }
-    }
-
-    public boolean isSingleton() {
-      return singleton;
-    }
-
-    public void setSingleton(final boolean singleton) {
-      this.singleton = singleton;
-    }
-
-    @Override
-    public String toString() {
-      return name + ": " + links;
-    }
-  }
-
-  private static class NavigationLink {
-
-    private final String name;
-
-    private final String targetName;
-
-    private final boolean feed;
-
-    public NavigationLink(final String name, final String targetName, final boolean feed) {
-      this.name = name;
-      this.targetName = targetName;
-      this.feed = feed;
-    }
-
-    public String getName() {
-      return name;
-    }
-
-    public String getTargetName() {
-      return targetName;
-    }
-
-    public boolean isFeed() {
-      return feed;
-    }
-
-    @Override
-    public String toString() {
-      return name + "(feed: " + isFeed() + ")";
-    }
-  }
-}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/fit/src/main/java/org/apache/olingo/fit/utils/XMLUtilities.java
----------------------------------------------------------------------
diff --git a/fit/src/main/java/org/apache/olingo/fit/utils/XMLUtilities.java b/fit/src/main/java/org/apache/olingo/fit/utils/XMLUtilities.java
index 1078e2f..c7930f0 100644
--- a/fit/src/main/java/org/apache/olingo/fit/utils/XMLUtilities.java
+++ b/fit/src/main/java/org/apache/olingo/fit/utils/XMLUtilities.java
@@ -38,6 +38,7 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.regex.Pattern;
 
 import javax.ws.rs.NotFoundException;
 import javax.xml.namespace.QName;
@@ -61,6 +62,8 @@ import org.apache.olingo.fit.metadata.NavigationProperty;
 
 public class XMLUtilities extends AbstractUtilities {
 
+  private static final Pattern ENTITY_URI_PATTERN = Pattern.compile(".*\\/.*\\(.*\\)");
+
   protected static XMLInputFactory ifactory = null;
 
   protected static XMLOutputFactory ofactory = null;

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/fit/src/test/java/org/apache/olingo/fit/proxy/demo/odatademo/types/Customer.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/proxy/demo/odatademo/types/Customer.java b/fit/src/test/java/org/apache/olingo/fit/proxy/demo/odatademo/types/Customer.java
index 405ce0a..b9d15cc 100644
--- a/fit/src/test/java/org/apache/olingo/fit/proxy/demo/odatademo/types/Customer.java
+++ b/fit/src/test/java/org/apache/olingo/fit/proxy/demo/odatademo/types/Customer.java
@@ -18,9 +18,7 @@
  */
 package org.apache.olingo.fit.proxy.demo.odatademo.types;
 
-// CHECKSTYLE:OFF (Maven checkstyle)
 import java.util.concurrent.Future;
-// CHECKSTYLE:ON (Maven checkstyle)
 
 import org.apache.olingo.ext.proxy.api.annotations.Key;
 
@@ -30,9 +28,7 @@ import org.apache.olingo.ext.proxy.api.annotations.Key;
     hasStream = false,
     isAbstract = false,
     baseType = "ODataDemo.Person")
-public interface Customer
-    extends org.apache.olingo.ext.proxy.api.Annotatable,
-        Person {
+public interface Customer extends Person {
 
   @Override
   Customer load();

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/fit/src/test/java/org/apache/olingo/fit/proxy/demo/odatademo/types/Employee.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/proxy/demo/odatademo/types/Employee.java b/fit/src/test/java/org/apache/olingo/fit/proxy/demo/odatademo/types/Employee.java
index 4b55f53..8b48599 100644
--- a/fit/src/test/java/org/apache/olingo/fit/proxy/demo/odatademo/types/Employee.java
+++ b/fit/src/test/java/org/apache/olingo/fit/proxy/demo/odatademo/types/Employee.java
@@ -18,9 +18,7 @@
  */
 package org.apache.olingo.fit.proxy.demo.odatademo.types;
 
-// CHECKSTYLE:OFF (Maven checkstyle)
 import java.util.concurrent.Future;
-// CHECKSTYLE:ON (Maven checkstyle)
 
 import org.apache.olingo.ext.proxy.api.annotations.Key;
 
@@ -30,9 +28,7 @@ import org.apache.olingo.ext.proxy.api.annotations.Key;
     hasStream = false,
     isAbstract = false,
     baseType = "ODataDemo.Person")
-public interface Employee
-    extends org.apache.olingo.ext.proxy.api.Annotatable,
-        Person {
+public interface Employee extends Person {
 
   @Override
   Employee load();

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/fit/src/test/java/org/apache/olingo/fit/proxy/demo/odatademo/types/FeaturedProduct.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/proxy/demo/odatademo/types/FeaturedProduct.java b/fit/src/test/java/org/apache/olingo/fit/proxy/demo/odatademo/types/FeaturedProduct.java
index 0d09511..b38852c 100644
--- a/fit/src/test/java/org/apache/olingo/fit/proxy/demo/odatademo/types/FeaturedProduct.java
+++ b/fit/src/test/java/org/apache/olingo/fit/proxy/demo/odatademo/types/FeaturedProduct.java
@@ -18,9 +18,7 @@
  */
 package org.apache.olingo.fit.proxy.demo.odatademo.types;
 
-// CHECKSTYLE:OFF (Maven checkstyle)
 import java.util.concurrent.Future;
-// CHECKSTYLE:ON (Maven checkstyle)
 
 import org.apache.olingo.ext.proxy.api.annotations.Key;
 
@@ -30,9 +28,7 @@ import org.apache.olingo.ext.proxy.api.annotations.Key;
     hasStream = false,
     isAbstract = false,
     baseType = "ODataDemo.Product")
-public interface FeaturedProduct
-    extends org.apache.olingo.ext.proxy.api.Annotatable,
-        Product {
+public interface FeaturedProduct extends Product {
 
   @Override
   FeaturedProduct load();

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/fit/src/test/java/org/apache/olingo/fit/proxy/opentype/microsoft/test/odata/services/opentypesservice/types/IndexedRow.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/proxy/opentype/microsoft/test/odata/services/opentypesservice/types/IndexedRow.java b/fit/src/test/java/org/apache/olingo/fit/proxy/opentype/microsoft/test/odata/services/opentypesservice/types/IndexedRow.java
index 2de8869..f2618f2 100644
--- a/fit/src/test/java/org/apache/olingo/fit/proxy/opentype/microsoft/test/odata/services/opentypesservice/types/IndexedRow.java
+++ b/fit/src/test/java/org/apache/olingo/fit/proxy/opentype/microsoft/test/odata/services/opentypesservice/types/IndexedRow.java
@@ -18,11 +18,8 @@
  */
 package org.apache.olingo.fit.proxy.opentype.microsoft.test.odata.services.opentypesservice.types;
 
-// CHECKSTYLE:OFF (Maven checkstyle)
 import java.util.concurrent.Future;
-// CHECKSTYLE:ON (Maven checkstyle)
 
-import org.apache.olingo.ext.proxy.api.AbstractOpenType;
 import org.apache.olingo.ext.proxy.api.annotations.Key;
 
 @org.apache.olingo.ext.proxy.api.annotations.Namespace("Microsoft.Test.OData.Services.OpenTypesServiceV4")
@@ -31,10 +28,7 @@ import org.apache.olingo.ext.proxy.api.annotations.Key;
     hasStream = false,
     isAbstract = false,
     baseType = "Microsoft.Test.OData.Services.OpenTypesServiceV4.Row")
-public interface IndexedRow
-    extends org.apache.olingo.ext.proxy.api.Annotatable,
-        Row,
-    AbstractOpenType {
+public interface IndexedRow extends Row {
 
   @Override
   IndexedRow load();

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/fit/src/test/java/org/apache/olingo/fit/proxy/staticservice/microsoft/test/odata/services/odatawcfservice/types/CreditCardPI.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/proxy/staticservice/microsoft/test/odata/services/odatawcfservice/types/CreditCardPI.java b/fit/src/test/java/org/apache/olingo/fit/proxy/staticservice/microsoft/test/odata/services/odatawcfservice/types/CreditCardPI.java
index 6873492..179f2e1 100644
--- a/fit/src/test/java/org/apache/olingo/fit/proxy/staticservice/microsoft/test/odata/services/odatawcfservice/types/CreditCardPI.java
+++ b/fit/src/test/java/org/apache/olingo/fit/proxy/staticservice/microsoft/test/odata/services/odatawcfservice/types/CreditCardPI.java
@@ -18,9 +18,7 @@
  */
 package org.apache.olingo.fit.proxy.staticservice.microsoft.test.odata.services.odatawcfservice.types;
 
-// CHECKSTYLE:OFF (Maven checkstyle)
 import java.util.concurrent.Future;
-// CHECKSTYLE:ON (Maven checkstyle)
 
 import org.apache.olingo.ext.proxy.api.AbstractEntitySet;
 import org.apache.olingo.ext.proxy.api.annotations.Key;
@@ -31,9 +29,7 @@ import org.apache.olingo.ext.proxy.api.annotations.Key;
     hasStream = false,
     isAbstract = false,
     baseType = "Microsoft.Test.OData.Services.ODataWCFService.PaymentInstrument")
-public interface CreditCardPI
-    extends org.apache.olingo.ext.proxy.api.Annotatable,
-        PaymentInstrument {
+public interface CreditCardPI extends PaymentInstrument {
 
   @Override
   CreditCardPI load();

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/fit/src/test/java/org/apache/olingo/fit/proxy/staticservice/microsoft/test/odata/services/odatawcfservice/types/Customer.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/proxy/staticservice/microsoft/test/odata/services/odatawcfservice/types/Customer.java b/fit/src/test/java/org/apache/olingo/fit/proxy/staticservice/microsoft/test/odata/services/odatawcfservice/types/Customer.java
index ed6fdc1..af66869 100644
--- a/fit/src/test/java/org/apache/olingo/fit/proxy/staticservice/microsoft/test/odata/services/odatawcfservice/types/Customer.java
+++ b/fit/src/test/java/org/apache/olingo/fit/proxy/staticservice/microsoft/test/odata/services/odatawcfservice/types/Customer.java
@@ -18,9 +18,7 @@
  */
 package org.apache.olingo.fit.proxy.staticservice.microsoft.test.odata.services.odatawcfservice.types;
 
-// CHECKSTYLE:OFF (Maven checkstyle)
 import java.util.concurrent.Future;
-// CHECKSTYLE:ON (Maven checkstyle)
 
 import org.apache.olingo.ext.proxy.api.annotations.Key;
 
@@ -30,9 +28,7 @@ import org.apache.olingo.ext.proxy.api.annotations.Key;
     hasStream = false,
     isAbstract = false,
     baseType = "Microsoft.Test.OData.Services.ODataWCFService.Person")
-public interface Customer
-    extends org.apache.olingo.ext.proxy.api.Annotatable,
-        Person {
+public interface Customer extends Person {
 
   @Override
   Customer load();

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/fit/src/test/java/org/apache/olingo/fit/proxy/staticservice/microsoft/test/odata/services/odatawcfservice/types/Employee.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/proxy/staticservice/microsoft/test/odata/services/odatawcfservice/types/Employee.java b/fit/src/test/java/org/apache/olingo/fit/proxy/staticservice/microsoft/test/odata/services/odatawcfservice/types/Employee.java
index f33ccb3..f0b4e80 100644
--- a/fit/src/test/java/org/apache/olingo/fit/proxy/staticservice/microsoft/test/odata/services/odatawcfservice/types/Employee.java
+++ b/fit/src/test/java/org/apache/olingo/fit/proxy/staticservice/microsoft/test/odata/services/odatawcfservice/types/Employee.java
@@ -18,9 +18,7 @@
  */
 package org.apache.olingo.fit.proxy.staticservice.microsoft.test.odata.services.odatawcfservice.types;
 
-// CHECKSTYLE:OFF (Maven checkstyle)
 import java.util.concurrent.Future;
-// CHECKSTYLE:ON (Maven checkstyle)
 
 import org.apache.olingo.ext.proxy.api.annotations.Key;
 
@@ -30,9 +28,7 @@ import org.apache.olingo.ext.proxy.api.annotations.Key;
     hasStream = false,
     isAbstract = false,
     baseType = "Microsoft.Test.OData.Services.ODataWCFService.Person")
-public interface Employee
-    extends org.apache.olingo.ext.proxy.api.Annotatable,
-        Person {
+public interface Employee extends Person {
 
   @Override
   Employee load();

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/fit/src/test/java/org/apache/olingo/fit/proxy/staticservice/microsoft/test/odata/services/odatawcfservice/types/PublicCompany.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/proxy/staticservice/microsoft/test/odata/services/odatawcfservice/types/PublicCompany.java b/fit/src/test/java/org/apache/olingo/fit/proxy/staticservice/microsoft/test/odata/services/odatawcfservice/types/PublicCompany.java
index cdace92..40144ef 100644
--- a/fit/src/test/java/org/apache/olingo/fit/proxy/staticservice/microsoft/test/odata/services/odatawcfservice/types/PublicCompany.java
+++ b/fit/src/test/java/org/apache/olingo/fit/proxy/staticservice/microsoft/test/odata/services/odatawcfservice/types/PublicCompany.java
@@ -18,12 +18,9 @@
  */
 package org.apache.olingo.fit.proxy.staticservice.microsoft.test.odata.services.odatawcfservice.types;
 
-// CHECKSTYLE:OFF (Maven checkstyle)
 import java.util.concurrent.Future;
-// CHECKSTYLE:ON (Maven checkstyle)
 
 import org.apache.olingo.ext.proxy.api.AbstractEntitySet;
-import org.apache.olingo.ext.proxy.api.AbstractOpenType;
 import org.apache.olingo.ext.proxy.api.annotations.Key;
 
 @org.apache.olingo.ext.proxy.api.annotations.Namespace("Microsoft.Test.OData.Services.ODataWCFService")
@@ -32,10 +29,7 @@ import org.apache.olingo.ext.proxy.api.annotations.Key;
     hasStream = false,
     isAbstract = false,
     baseType = "Microsoft.Test.OData.Services.ODataWCFService.Company")
-public interface PublicCompany
-    extends org.apache.olingo.ext.proxy.api.Annotatable,
-        Company,
-    AbstractOpenType {
+public interface PublicCompany extends Company {
 
   @Override
   PublicCompany load();

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/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
index 94867af..bac2927 100644
--- 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
@@ -24,6 +24,7 @@ import static org.junit.Assert.assertNull;
 import static org.junit.Assert.fail;
 
 import java.net.URI;
+import java.util.EnumMap;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -553,11 +554,11 @@ public class EntityReferencesITCase extends AbstractParamTecSvcITCase {
            .getReferenceSingleChangeRequest(new URI(SERVICE_URI), uri, reference)
            .execute();
       assertEquals(HttpStatusCode.NO_CONTENT.getStatusCode(), response.getStatusCode());
-      
+
       final String cookie = response.getHeader(HttpHeader.SET_COOKIE).iterator().next();
-      Map<QueryOption, Object> expandOptions = new HashMap<QueryOption, Object>();
+      Map<QueryOption, Object> expandOptions = new EnumMap<QueryOption, Object>(QueryOption.class);
       expandOptions.put(QueryOption.EXPAND, NAV_PROPERTY_ET_KEY_NAV_ONE);
-      
+
       final URI getURI = getClient().newURIBuilder(SERVICE_URI)
                                .appendEntitySetSegment(ES_TWO_KEY_NAV)
                                .appendKeySegment(esTwoKeyNavKey)
@@ -601,12 +602,12 @@ public class EntityReferencesITCase extends AbstractParamTecSvcITCase {
            .getReferenceAddingRequest(new URI(SERVICE_URI), uri, reference)
            .execute();
       assertEquals(HttpStatusCode.NO_CONTENT.getStatusCode(), response.getStatusCode());
-      
+
       final String cookie = response.getHeader(HttpHeader.SET_COOKIE).iterator().next();
-      final Map<QueryOption, Object> expandOptions = new HashMap<QueryOption, Object>();
+      final Map<QueryOption, Object> expandOptions = new EnumMap<QueryOption, Object>(QueryOption.class);
       expandOptions.put(QueryOption.EXPAND, NAV_PROPERTY_ET_KEY_NAV_MANY);
       expandOptions.put(QueryOption.FILTER, "PropertyInt16 eq 1");
-      
+
       final URI getURI = getClient().newURIBuilder(SERVICE_URI)
                                .appendEntitySetSegment(ES_TWO_KEY_NAV)
                                .appendKeySegment(esTwoKeyNavKey)

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/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 507b9a9..0f3743b 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
@@ -23,6 +23,8 @@ import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.fail;
 
 import java.net.URI;
+import java.util.Collections;
+import java.util.EnumMap;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -49,11 +51,10 @@ public class ExpandWithSystemQueryOptionsITCase extends AbstractParamTecSvcITCas
 
   @Test
   public void filter() {
-    Map<QueryOption, Object> options = new HashMap<QueryOption, Object>();
-    options.put(QueryOption.FILTER, "PropertyString eq '2'");
-
     final ODataRetrieveResponse<ClientEntitySet> response =
-        buildRequest(ES_TWO_KEY_NAV, NAV_PROPERTY_ET_TWO_KEY_NAV_MANY, options);
+        buildRequest(ES_TWO_KEY_NAV, NAV_PROPERTY_ET_TWO_KEY_NAV_MANY,
+            Collections.singletonMap(QueryOption.FILTER, (Object) "PropertyString eq '2'"));
+
     final List<ClientEntity> entities = response.getBody().getEntities();
     assertEquals(4, entities.size());
 
@@ -87,11 +88,9 @@ public class ExpandWithSystemQueryOptionsITCase extends AbstractParamTecSvcITCas
 
   @Test
   public void orderBy() {
-    Map<QueryOption, Object> options = new HashMap<QueryOption, Object>();
-    options.put(QueryOption.ORDERBY, "PropertyString desc");
-
     final ODataRetrieveResponse<ClientEntitySet> response =
-        buildRequest(ES_TWO_KEY_NAV, NAV_PROPERTY_ET_TWO_KEY_NAV_MANY, options);
+        buildRequest(ES_TWO_KEY_NAV, NAV_PROPERTY_ET_TWO_KEY_NAV_MANY,
+            Collections.<QueryOption, Object> singletonMap(QueryOption.ORDERBY, "PropertyString desc"));
     final List<ClientEntity> entities = response.getBody().getEntities();
     assertEquals(4, entities.size());
 
@@ -117,11 +116,9 @@ public class ExpandWithSystemQueryOptionsITCase extends AbstractParamTecSvcITCas
 
   @Test
   public void skip() {
-    Map<QueryOption, Object> options = new HashMap<QueryOption, Object>();
-    options.put(QueryOption.SKIP, "1");
-
     final ODataRetrieveResponse<ClientEntitySet> response =
-        buildRequest(ES_KEY_NAV, NAV_PROPERTY_ET_KEY_NAV_MANY, options);
+        buildRequest(ES_KEY_NAV, NAV_PROPERTY_ET_KEY_NAV_MANY,
+            Collections.singletonMap(QueryOption.SKIP, (Object) "1"));
     final List<ClientEntity> entities = response.getBody().getEntities();
     assertEquals(3, entities.size());
 
@@ -148,11 +145,9 @@ public class ExpandWithSystemQueryOptionsITCase extends AbstractParamTecSvcITCas
 
   @Test
   public void top() {
-    Map<QueryOption, Object> options = new HashMap<QueryOption, Object>();
-    options.put(QueryOption.TOP, "1");
-
     final ODataRetrieveResponse<ClientEntitySet> response =
-        buildRequest(ES_KEY_NAV, NAV_PROPERTY_ET_KEY_NAV_MANY, options);
+        buildRequest(ES_KEY_NAV, NAV_PROPERTY_ET_KEY_NAV_MANY,
+            Collections.<QueryOption, Object> singletonMap(QueryOption.TOP, "1"));
     final List<ClientEntity> entities = response.getBody().getEntities();
     assertEquals(3, entities.size());
 
@@ -179,7 +174,7 @@ public class ExpandWithSystemQueryOptionsITCase extends AbstractParamTecSvcITCas
 
   @Test
   public void combinedSystemQueryOptions() {
-    Map<QueryOption, Object> options = new HashMap<QueryOption, Object>();
+    Map<QueryOption, Object> options = new EnumMap<QueryOption, Object>(QueryOption.class);
     options.put(QueryOption.SELECT, "PropertyInt16,PropertyString");
     options.put(QueryOption.FILTER, "PropertyInt16 eq 1");
     options.put(QueryOption.SKIP, "1");
@@ -217,7 +212,7 @@ public class ExpandWithSystemQueryOptionsITCase extends AbstractParamTecSvcITCas
   @Ignore("Server do not support navigation property count annotations")
   public void count() {
     final ODataClient client = getEdmEnabledClient();
-    Map<QueryOption, Object> options = new HashMap<QueryOption, Object>();
+    Map<QueryOption, Object> options = new EnumMap<QueryOption, Object>(QueryOption.class);
     options.put(QueryOption.SELECT, "PropertyInt16");
     options.put(QueryOption.COUNT, true);
 
@@ -255,14 +250,14 @@ public class ExpandWithSystemQueryOptionsITCase extends AbstractParamTecSvcITCas
   public void singleEntityWithExpand() {
     /* A single entity request will be dispatched to a different processor method than entity set request */
     final ODataClient client = getEdmEnabledClient();
-    Map<QueryOption, Object> options = new HashMap<QueryOption, Object>();
-    options.put(QueryOption.FILTER, "PropertyInt16 lt 2");
     Map<String, Object> keys = new HashMap<String, Object>();
     keys.put("PropertyInt16", 1);
     keys.put("PropertyString", "1");
 
     final URI uri = client.newURIBuilder(SERVICE_URI).appendEntitySetSegment(ES_TWO_KEY_NAV).appendKeySegment(keys)
-        .expandWithOptions(NAV_PROPERTY_ET_KEY_NAV_MANY, options).build();
+        .expandWithOptions(NAV_PROPERTY_ET_KEY_NAV_MANY,
+            Collections.singletonMap(QueryOption.FILTER, (Object) "PropertyInt16 lt 2"))
+        .build();
     final ODataRetrieveResponse<ClientEntity> response =
             client.getRetrieveRequestFactory().getEntityRequest(uri).execute();
     assertEquals(HttpStatusCode.OK.getStatusCode(), response.getStatusCode());
@@ -275,11 +270,12 @@ public class ExpandWithSystemQueryOptionsITCase extends AbstractParamTecSvcITCas
 
   @Test
   public void URIEscaping() {
-    Map<QueryOption, Object> options = new HashMap<QueryOption, Object>();
-    options.put(QueryOption.FILTER, "PropertyInt16 eq 1"
-        + " and PropertyComp/PropertyComp/PropertyDuration eq duration'PT1S' and length(PropertyString) gt 4");
     final ODataRetrieveResponse<ClientEntitySet> response =
-        buildRequest(ES_TWO_KEY_NAV, NAV_PROPERTY_ET_TWO_KEY_NAV_MANY, options);
+        buildRequest(ES_TWO_KEY_NAV, NAV_PROPERTY_ET_TWO_KEY_NAV_MANY,
+            Collections.<QueryOption, Object> singletonMap(QueryOption.FILTER,
+                "PropertyInt16 eq 1"
+                + " and PropertyComp/PropertyComp/PropertyDuration eq duration'PT1S'"
+                + " and length(PropertyString) gt 4"));
     final List<ClientEntity> entities = response.getBody().getEntities();
 
     assertEquals(HttpStatusCode.OK.getStatusCode(), response.getStatusCode());
@@ -296,7 +292,7 @@ public class ExpandWithSystemQueryOptionsITCase extends AbstractParamTecSvcITCas
     // Define filters to select explicit the entities at any level => Circle
 
     final ODataClient client = getEdmEnabledClient();
-    Map<QueryOption, Object> options = new HashMap<QueryOption, Object>();
+    Map<QueryOption, Object> options = new EnumMap<QueryOption, Object>(QueryOption.class);
     options.put(QueryOption.EXPAND, NAV_PROPERTY_ET_TWO_KEY_NAV_MANY
         + "($expand=" + NAV_PROPERTY_ET_TWO_KEY_NAV_MANY
         + "($expand=" + NAV_PROPERTY_ET_TWO_KEY_NAV_MANY + "))");
@@ -371,7 +367,7 @@ public class ExpandWithSystemQueryOptionsITCase extends AbstractParamTecSvcITCas
   @Test
   public void systemQueryOptionOnThirdLevel() {
     final ODataClient client = getEdmEnabledClient();
-    Map<QueryOption, Object> options = new HashMap<QueryOption, Object>();
+    Map<QueryOption, Object> options = new EnumMap<QueryOption, Object>(QueryOption.class);
     options.put(QueryOption.EXPAND, NAV_PROPERTY_ET_TWO_KEY_NAV_MANY
         + "($expand=" + NAV_PROPERTY_ET_TWO_KEY_NAV_MANY
         + "($expand=" + NAV_PROPERTY_ET_TWO_KEY_NAV_MANY
@@ -444,7 +440,7 @@ public class ExpandWithSystemQueryOptionsITCase extends AbstractParamTecSvcITCas
   @Test
   public void expandWithSearchQuery() {
     final ODataClient client = getEdmEnabledClient();
-    Map<QueryOption, Object> expandOptions = new HashMap<QueryOption, Object>();
+    Map<QueryOption, Object> expandOptions = new EnumMap<QueryOption, Object>(QueryOption.class);
     expandOptions.put(QueryOption.SEARCH, "abc");
     expandOptions.put(QueryOption.FILTER, "PropertyInt16 eq 1");
     
@@ -464,12 +460,10 @@ public class ExpandWithSystemQueryOptionsITCase extends AbstractParamTecSvcITCas
   @Test
   public void expandWithLevels() {
     final ODataClient client = getEdmEnabledClient();
-    Map<QueryOption, Object> expandOptions = new HashMap<QueryOption, Object>();
-    expandOptions.put(QueryOption.LEVELS, 2);
 
     // expand=*($levels=2)
     URI uri = client.newURIBuilder(SERVICE_URI).appendEntitySetSegment(ES_KEY_NAV)
-            .expandWithOptions("*", expandOptions)
+            .expandWithOptions("*", Collections.<QueryOption, Object> singletonMap(QueryOption.LEVELS, 2))
             .build();
 
     try {
@@ -479,10 +473,9 @@ public class ExpandWithSystemQueryOptionsITCase extends AbstractParamTecSvcITCas
     }
 
     // expand=NavPropertyETTwoKeyNavMany($levels=2)
-    expandOptions.clear();
-    expandOptions.put(QueryOption.LEVELS, 2);
     uri = client.newURIBuilder(SERVICE_URI).appendEntitySetSegment(ES_KEY_NAV)
-            .expandWithOptions(NAV_PROPERTY_ET_TWO_KEY_NAV_MANY, expandOptions)
+            .expandWithOptions(NAV_PROPERTY_ET_TWO_KEY_NAV_MANY,
+                Collections.<QueryOption, Object> singletonMap(QueryOption.LEVELS, 2))
             .build();
 
     try {
@@ -492,10 +485,10 @@ public class ExpandWithSystemQueryOptionsITCase extends AbstractParamTecSvcITCas
     }
 
     // expand=NavPropertyETTwoKeyNavMany($expand=NavPropertyETTwoKeyNavMany($levels=2))
-    expandOptions.clear();
-    expandOptions.put(QueryOption.EXPAND, NAV_PROPERTY_ET_TWO_KEY_NAV_MANY + "($levels=2)");
     uri = client.newURIBuilder(SERVICE_URI).appendEntitySetSegment(ES_KEY_NAV)
-            .expandWithOptions(NAV_PROPERTY_ET_TWO_KEY_NAV_MANY, expandOptions)
+            .expandWithOptions(NAV_PROPERTY_ET_TWO_KEY_NAV_MANY,
+                Collections.<QueryOption, Object> singletonMap(QueryOption.EXPAND,
+                    NAV_PROPERTY_ET_TWO_KEY_NAV_MANY + "($levels=2)"))
             .build();
 
     try {
@@ -505,10 +498,9 @@ public class ExpandWithSystemQueryOptionsITCase extends AbstractParamTecSvcITCas
     }
 
     // expand=NavPropertyETTwoKeyNavMany($expand=NavPropertyETTwoKeyNavMany($levels=2);$levels=3)
-    expandOptions.clear();
-    expandOptions.put(QueryOption.LEVELS, 2);
     uri = client.newURIBuilder(SERVICE_URI).appendEntitySetSegment(ES_KEY_NAV)
-            .expandWithOptions(NAV_PROPERTY_ET_TWO_KEY_NAV_MANY, expandOptions)
+            .expandWithOptions(NAV_PROPERTY_ET_TWO_KEY_NAV_MANY,
+                Collections.<QueryOption, Object> singletonMap(QueryOption.LEVELS, 2))
             .build();
 
     try {
@@ -518,7 +510,7 @@ public class ExpandWithSystemQueryOptionsITCase extends AbstractParamTecSvcITCas
     }
 
     // expand=NavPropertyETTwoKeyNavMany($expand=NavPropertyETTwoKeyNavMany($levels=2))
-    expandOptions.clear();
+    Map<QueryOption, Object> expandOptions = new EnumMap<QueryOption, Object>(QueryOption.class);
     expandOptions.put(QueryOption.EXPAND, NAV_PROPERTY_ET_TWO_KEY_NAV_MANY + "($levels=2)");
     expandOptions.put(QueryOption.LEVELS, 3);
     uri = client.newURIBuilder(SERVICE_URI).appendEntitySetSegment(ES_KEY_NAV)

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/lib/client-core/src/main/java/org/apache/olingo/client/core/domain/AbstractClientEntitySet.java
----------------------------------------------------------------------
diff --git a/lib/client-core/src/main/java/org/apache/olingo/client/core/domain/AbstractClientEntitySet.java b/lib/client-core/src/main/java/org/apache/olingo/client/core/domain/AbstractClientEntitySet.java
deleted file mode 100644
index d59af93..0000000
--- a/lib/client-core/src/main/java/org/apache/olingo/client/core/domain/AbstractClientEntitySet.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * 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.client.core.domain;
-
-import java.net.URI;
-
-import org.apache.olingo.client.api.domain.AbstractClientPayload;
-import org.apache.olingo.client.api.domain.ClientEntitySet;
-
-public abstract class AbstractClientEntitySet extends AbstractClientPayload implements ClientEntitySet {
-
-  /**
-   * Link to the next page.
-   */
-  private URI next;
-
-  /**
-   * Number of ODataEntities contained in this entity set.
-   * <br/>
-   * If <tt>$count</tt> was requested, this value comes from there.
-   */
-  private Integer count;
-
-  /**
-   * Constructor.
-   */
-  public AbstractClientEntitySet() {
-    super(null);
-  }
-
-  /**
-   * Constructor.
-   * 
-   * @param next next link.
-   */
-  public AbstractClientEntitySet(final URI next) {
-    super(null);
-    this.next = next;
-  }
-
-  @Override
-  public URI getNext() {
-    return next;
-  }
-
-  @Override
-  public Integer getCount() {
-    return count;
-  }
-
-  @Override
-  public void setCount(final int count) {
-    this.count = count;
-  }
-
-  @Override
-  public int hashCode() {
-    final int prime = 31;
-    int result = super.hashCode();
-    result = prime * result + ((count == null) ? 0 : count.hashCode());
-    result = prime * result + ((next == null) ? 0 : next.hashCode());
-    return result;
-  }
-
-  @Override
-  public boolean equals(Object obj) {
-    if (this == obj) {
-      return true;
-    }
-    if (!super.equals(obj)) {
-      return false;
-    }
-    if (!(obj instanceof AbstractClientEntitySet)) {
-      return false;
-    }
-    AbstractClientEntitySet other = (AbstractClientEntitySet) obj;
-    if (count == null) {
-      if (other.count != null) {
-        return false;
-      }
-    } else if (!count.equals(other.count)) {
-      return false;
-    }
-    if (next == null) {
-      if (other.next != null) {
-        return false;
-      }
-    } else if (!next.equals(other.next)) {
-      return false;
-    }
-    return true;
-  }
-
-  @Override
-  public String toString() {
-    return "AbstractClientEntitySet [next=" + next + ", count=" + count + "super[" + super.toString() + "]]";
-  }
-}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/lib/client-core/src/main/java/org/apache/olingo/client/core/domain/ClientCollectionValueImpl.java
----------------------------------------------------------------------
diff --git a/lib/client-core/src/main/java/org/apache/olingo/client/core/domain/ClientCollectionValueImpl.java b/lib/client-core/src/main/java/org/apache/olingo/client/core/domain/ClientCollectionValueImpl.java
index c83fceb..2a3aebc 100644
--- a/lib/client-core/src/main/java/org/apache/olingo/client/core/domain/ClientCollectionValueImpl.java
+++ b/lib/client-core/src/main/java/org/apache/olingo/client/core/domain/ClientCollectionValueImpl.java
@@ -29,7 +29,7 @@ import org.apache.olingo.client.api.domain.ClientEnumValue;
 import org.apache.olingo.client.api.domain.ClientValue;
 
 public class ClientCollectionValueImpl<OV extends ClientValue> extends AbstractClientValue
-        implements ClientCollectionValue<OV>, ClientValue {
+        implements ClientCollectionValue<OV> {
 
   /**
    * Constructor.

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/lib/client-core/src/main/java/org/apache/olingo/client/core/domain/ClientEntitySetImpl.java
----------------------------------------------------------------------
diff --git a/lib/client-core/src/main/java/org/apache/olingo/client/core/domain/ClientEntitySetImpl.java b/lib/client-core/src/main/java/org/apache/olingo/client/core/domain/ClientEntitySetImpl.java
index 29ede4c..21e13b4 100644
--- a/lib/client-core/src/main/java/org/apache/olingo/client/core/domain/ClientEntitySetImpl.java
+++ b/lib/client-core/src/main/java/org/apache/olingo/client/core/domain/ClientEntitySetImpl.java
@@ -22,11 +22,24 @@ import java.net.URI;
 import java.util.ArrayList;
 import java.util.List;
 
+import org.apache.olingo.client.api.domain.AbstractClientPayload;
 import org.apache.olingo.client.api.domain.ClientAnnotation;
 import org.apache.olingo.client.api.domain.ClientEntity;
 import org.apache.olingo.client.api.domain.ClientEntitySet;
 
-public class ClientEntitySetImpl extends AbstractClientEntitySet implements ClientEntitySet {
+public class ClientEntitySetImpl extends AbstractClientPayload implements ClientEntitySet {
+
+  /**
+   * Link to the next page.
+   */
+  private final URI next;
+
+  /**
+   * Number of ODataEntities contained in this entity set.
+   * <br/>
+   * If <tt>$count</tt> was requested, this value comes from there.
+   */
+  private Integer count;
 
   private URI deltaLink;
 
@@ -35,11 +48,28 @@ public class ClientEntitySetImpl extends AbstractClientEntitySet implements Clie
   private final List<ClientAnnotation> annotations = new ArrayList<ClientAnnotation>();
 
   public ClientEntitySetImpl() {
-    super();
+    super(null);
+    next = null;
   }
 
   public ClientEntitySetImpl(final URI next) {
-    super(next);
+    super(null);
+    this.next = next;
+  }
+
+  @Override
+  public URI getNext() {
+    return next;
+  }
+
+  @Override
+  public Integer getCount() {
+    return count;
+  }
+
+  @Override
+  public void setCount(final int count) {
+    this.count = count;
   }
 
   @Override
@@ -66,6 +96,8 @@ public class ClientEntitySetImpl extends AbstractClientEntitySet implements Clie
   public int hashCode() {
     final int prime = 31;
     int result = super.hashCode();
+    result = prime * result + ((count == null) ? 0 : count.hashCode());
+    result = prime * result + ((next == null) ? 0 : next.hashCode());
     result = prime * result + ((annotations == null) ? 0 : annotations.hashCode());
     result = prime * result + ((deltaLink == null) ? 0 : deltaLink.hashCode());
     result = prime * result + ((entities == null) ? 0 : entities.hashCode());
@@ -77,40 +109,20 @@ public class ClientEntitySetImpl extends AbstractClientEntitySet implements Clie
     if (this == obj) {
       return true;
     }
-    if (!super.equals(obj)) {
-      return false;
-    }
-    if (!(obj instanceof ClientEntitySetImpl)) {
-      return false;
-    }
-    ClientEntitySetImpl other = (ClientEntitySetImpl) obj;
-    if (annotations == null) {
-      if (other.annotations != null) {
-        return false;
-      }
-    } else if (!annotations.equals(other.annotations)) {
-      return false;
-    }
-    if (deltaLink == null) {
-      if (other.deltaLink != null) {
-        return false;
-      }
-    } else if (!deltaLink.equals(other.deltaLink)) {
-      return false;
-    }
-    if (entities == null) {
-      if (other.entities != null) {
-        return false;
-      }
-    } else if (!entities.equals(other.entities)) {
+    if (obj == null || !(obj instanceof ClientEntitySetImpl)) {
       return false;
     }
-    return true;
+    final ClientEntitySetImpl other = (ClientEntitySetImpl) obj;
+    return (count == null ? other.count == null : count.equals(other.count))
+        && (next == null ? other.next == null : next.equals(other.next))
+        && annotations.equals(other.annotations)
+        && (deltaLink == null ? other.deltaLink == null : deltaLink.equals(other.deltaLink))
+        && entities.equals(other.entities);
   }
 
   @Override
   public String toString() {
     return "ClientEntitySetImpl [deltaLink=" + deltaLink + ", entities=" + entities + ", annotations=" + annotations
-        + "super[" + super.toString() + "]]";
+        + ", next=" + next + ", count=" + count + "super[" + super.toString() + "]]";
   }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/lib/client-core/src/main/java/org/apache/olingo/client/core/domain/ClientPrimitiveValueImpl.java
----------------------------------------------------------------------
diff --git a/lib/client-core/src/main/java/org/apache/olingo/client/core/domain/ClientPrimitiveValueImpl.java b/lib/client-core/src/main/java/org/apache/olingo/client/core/domain/ClientPrimitiveValueImpl.java
index cdfe623..4824632 100644
--- a/lib/client-core/src/main/java/org/apache/olingo/client/core/domain/ClientPrimitiveValueImpl.java
+++ b/lib/client-core/src/main/java/org/apache/olingo/client/core/domain/ClientPrimitiveValueImpl.java
@@ -21,11 +21,10 @@ package org.apache.olingo.client.core.domain;
 import java.math.BigDecimal;
 import java.util.UUID;
 
-import org.apache.olingo.commons.api.Constants;
 import org.apache.olingo.client.api.domain.AbstractClientValue;
 import org.apache.olingo.client.api.domain.ClientEnumValue;
 import org.apache.olingo.client.api.domain.ClientPrimitiveValue;
-import org.apache.olingo.client.api.domain.ClientValue;
+import org.apache.olingo.commons.api.Constants;
 import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
 import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
 import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
@@ -33,7 +32,7 @@ import org.apache.olingo.commons.api.edm.EdmType;
 import org.apache.olingo.commons.api.edm.constants.EdmTypeKind;
 import org.apache.olingo.commons.core.edm.primitivetype.EdmPrimitiveTypeFactory;
 
-public class ClientPrimitiveValueImpl extends AbstractClientValue implements ClientValue, ClientPrimitiveValue {
+public class ClientPrimitiveValueImpl extends AbstractClientValue implements ClientPrimitiveValue {
 
   public static class BuilderImpl implements Builder {
 

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/lib/client-core/src/main/java/org/apache/olingo/client/core/domain/ClientPropertyImpl.java
----------------------------------------------------------------------
diff --git a/lib/client-core/src/main/java/org/apache/olingo/client/core/domain/ClientPropertyImpl.java b/lib/client-core/src/main/java/org/apache/olingo/client/core/domain/ClientPropertyImpl.java
index f78c506..8c8c3ee 100644
--- a/lib/client-core/src/main/java/org/apache/olingo/client/core/domain/ClientPropertyImpl.java
+++ b/lib/client-core/src/main/java/org/apache/olingo/client/core/domain/ClientPropertyImpl.java
@@ -18,30 +18,21 @@
  */
 package org.apache.olingo.client.core.domain;
 
-import org.apache.olingo.client.api.domain.ClientAnnotatable;
+import java.util.ArrayList;
+import java.util.List;
+
 import org.apache.olingo.client.api.domain.ClientAnnotation;
-import org.apache.olingo.client.api.domain.ClientCollectionValue;
-import org.apache.olingo.client.api.domain.ClientComplexValue;
-import org.apache.olingo.client.api.domain.ClientEnumValue;
-import org.apache.olingo.client.api.domain.ClientPrimitiveValue;
 import org.apache.olingo.client.api.domain.ClientProperty;
-import org.apache.olingo.client.api.domain.ClientValuable;
 import org.apache.olingo.client.api.domain.ClientValue;
 
-import java.util.ArrayList;
-import java.util.List;
-
-public final class ClientPropertyImpl implements ClientProperty, ClientAnnotatable, ClientValuable {
+public final class ClientPropertyImpl extends ClientValuableImpl implements ClientProperty {
 
   private final List<ClientAnnotation> annotations = new ArrayList<ClientAnnotation>();
   private final String name;
-  private final ClientValue value;
-  private final ClientValuable valuable;
 
   public ClientPropertyImpl(final String name, final ClientValue value) {
+    super(value);
     this.name = name;
-    this.value = value;
-    this.valuable = new ClientValuableImpl(value);
   }
 
   /**
@@ -55,16 +46,6 @@ public final class ClientPropertyImpl implements ClientProperty, ClientAnnotatab
   }
 
   /**
-   * Returns property value.
-   *
-   * @return property value.
-   */
-  @Override
-  public ClientValue getValue() {
-    return value;
-  }
-
-  /**
    * Checks if has null value.
    *
    * @return 'TRUE' if has null value; 'FALSE' otherwise.
@@ -74,87 +55,18 @@ public final class ClientPropertyImpl implements ClientProperty, ClientAnnotatab
     return value == null || value.isPrimitive() && value.asPrimitive().toValue() == null;
   }
 
-  /**
-   * Checks if has primitive value.
-   *
-   * @return 'TRUE' if has primitive value; 'FALSE' otherwise.
-   */
-  @Override
-  public boolean hasPrimitiveValue() {
-    return !hasNullValue() && value.isPrimitive();
-  }
-
-  /**
-   * Gets primitive value.
-   *
-   * @return primitive value if exists; null otherwise.
-   */
-  @Override
-  public ClientPrimitiveValue getPrimitiveValue() {
-    return hasPrimitiveValue() ? value.asPrimitive() : null;
-  }
-
-  /**
-   * Checks if has complex value.
-   *
-   * @return 'TRUE' if has complex value; 'FALSE' otherwise.
-   */
-  @Override
-  public boolean hasComplexValue() {
-    return !hasNullValue() && value.isComplex();
-  }
-
-  /**
-   * Checks if has collection value.
-   *
-   * @return 'TRUE' if has collection value; 'FALSE' otherwise.
-   */
-  @Override
-  public boolean hasCollectionValue() {
-    return !hasNullValue() && value.isCollection();
-  }
-
   @Override
   public boolean equals(Object obj) {
     if (this == obj) {
       return true;
     }
-    if (obj == null) {
-      return false;
-    }
-    if (!(obj instanceof ClientPropertyImpl)) {
-      return false;
-    }
-    ClientPropertyImpl other = (ClientPropertyImpl) obj;
-    if (annotations == null) {
-      if (other.annotations != null) {
-        return false;
-      }
-    } else if (!annotations.equals(other.annotations)) {
-      return false;
-    }
-    if (name == null) {
-      if (other.name != null) {
-        return false;
-      }
-    } else if (!name.equals(other.name)) {
-      return false;
-    }
-    if (valuable == null) {
-      if (other.valuable != null) {
-        return false;
-      }
-    } else if (!valuable.equals(other.valuable)) {
+    if (obj == null || !(obj instanceof ClientPropertyImpl)) {
       return false;
     }
-    if (value == null) {
-      if (other.value != null) {
-        return false;
-      }
-    } else if (!value.equals(other.value)) {
-      return false;
-    }
-    return true;
+    final ClientPropertyImpl other = (ClientPropertyImpl) obj;
+    return annotations.equals(other.annotations)
+        && (name == null ? other.name == null : name.equals(other.name))
+        && (value == null ? other.value == null : value.equals(other.value));
   }
 
   @Override
@@ -163,42 +75,17 @@ public final class ClientPropertyImpl implements ClientProperty, ClientAnnotatab
     int result = 1;
     result = prime * result + ((annotations == null) ? 0 : annotations.hashCode());
     result = prime * result + ((name == null) ? 0 : name.hashCode());
-    result = prime * result + ((valuable == null) ? 0 : valuable.hashCode());
     result = prime * result + ((value == null) ? 0 : value.hashCode());
     return result;
   }
 
   @Override
-  public boolean hasEnumValue() {
-    return valuable.hasEnumValue();
-  }
-
-  @Override
-  public ClientEnumValue getEnumValue() {
-    return valuable.getEnumValue();
-  }
-
-  @Override
-  public ClientComplexValue getComplexValue() {
-    return valuable.getComplexValue();
-  }
-
-  @Override
-  public ClientCollectionValue<ClientValue> getCollectionValue() {
-    return valuable.getCollectionValue();
-  }
-
-  @Override
   public List<ClientAnnotation> getAnnotations() {
     return annotations;
   }
 
   @Override
   public String toString() {
-    return "ODataPropertyImpl{"
-        + "name=" + getName()
-        + ",valuable=" + valuable
-        + ", annotations=" + annotations
-        + '}';
+    return "ClientPropertyImpl{" + "name=" + name + ", value=" + value + ", annotations=" + annotations + '}';
   }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/lib/client-core/src/main/java/org/apache/olingo/client/core/domain/ClientValuableImpl.java
----------------------------------------------------------------------
diff --git a/lib/client-core/src/main/java/org/apache/olingo/client/core/domain/ClientValuableImpl.java b/lib/client-core/src/main/java/org/apache/olingo/client/core/domain/ClientValuableImpl.java
index 4a032ce..4b94be6 100644
--- a/lib/client-core/src/main/java/org/apache/olingo/client/core/domain/ClientValuableImpl.java
+++ b/lib/client-core/src/main/java/org/apache/olingo/client/core/domain/ClientValuableImpl.java
@@ -25,9 +25,9 @@ import org.apache.olingo.client.api.domain.ClientPrimitiveValue;
 import org.apache.olingo.client.api.domain.ClientValuable;
 import org.apache.olingo.client.api.domain.ClientValue;
 
-public final class ClientValuableImpl implements ClientValuable {
+public class ClientValuableImpl implements ClientValuable {
 
-  private final ClientValue value;
+  protected final ClientValue value;
 
   public ClientValuableImpl(final ClientValue value) {
     this.value = value;
@@ -60,9 +60,7 @@ public final class ClientValuableImpl implements ClientValuable {
 
   @Override
   public ClientCollectionValue<ClientValue> getCollectionValue() {
-    return hasCollectionValue()
-        ? getValue().<ClientValue> asCollection()
-        : null;
+    return hasCollectionValue() ? getValue().<ClientValue> asCollection() : null;
   }
 
   @Override
@@ -72,9 +70,7 @@ public final class ClientValuableImpl implements ClientValuable {
 
   @Override
   public ClientComplexValue getComplexValue() {
-    return hasComplexValue()
-        ? getValue().asComplex()
-        : null;
+    return hasComplexValue() ? getValue().asComplex() : null;
   }
 
   @Override
@@ -84,9 +80,7 @@ public final class ClientValuableImpl implements ClientValuable {
 
   @Override
   public ClientEnumValue getEnumValue() {
-    return hasEnumValue()
-        ? getValue().asEnum()
-        : null;
+    return hasEnumValue() ? getValue().asEnum() : null;
   }
 
   @Override
@@ -99,9 +93,7 @@ public final class ClientValuableImpl implements ClientValuable {
     }
 
     ClientValuableImpl that = (ClientValuableImpl) o;
-
     return !(value != null ? !value.equals(that.value) : that.value != null);
-
   }
 
   @Override
@@ -111,8 +103,6 @@ public final class ClientValuableImpl implements ClientValuable {
 
   @Override
   public String toString() {
-    return "ClientValuableImpl{" +
-        "value=" + value +
-        '}';
+    return "ClientValuableImpl{" + "value=" + value + '}';
   }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/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 33144ec..f9f29e7 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
@@ -714,7 +714,7 @@ public class ODataBinderImpl implements ODataBinder {
       if (propertyType == null || propertyType.equals(EdmPrimitiveTypeKind.String.getFullQualifiedName().toString())) {
         typeInfo = new EdmTypeInfo.Builder().setTypeExpression(typeName.toString()).build();
       } else if(isPrimiteveType(typeName)) {
-        // Inheritance is not allowed for primitve types, so we use the type given by the EDM
+        // Inheritance is not allowed for primitive types, so we use the type given by the EDM.
         typeInfo = new EdmTypeInfo.Builder().setTypeExpression(typeName.toString()).build();
       } else {
         typeInfo = new EdmTypeInfo.Builder().setTypeExpression(propertyType).build();

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/lib/client-core/src/test/java/org/apache/olingo/client/core/AbstractTest.java
----------------------------------------------------------------------
diff --git a/lib/client-core/src/test/java/org/apache/olingo/client/core/AbstractTest.java b/lib/client-core/src/test/java/org/apache/olingo/client/core/AbstractTest.java
index bc116a8..d03b6d9 100644
--- a/lib/client-core/src/test/java/org/apache/olingo/client/core/AbstractTest.java
+++ b/lib/client-core/src/test/java/org/apache/olingo/client/core/AbstractTest.java
@@ -25,9 +25,7 @@ import org.junit.BeforeClass;
 
 public abstract class AbstractTest {
 
-  protected static ODataClient v4Client;
-
-  protected abstract ODataClient getClient();
+  protected static final ODataClient client = ODataClientFactory.getClient();
 
   @BeforeClass
   public static void setUp() {
@@ -38,11 +36,6 @@ public abstract class AbstractTest {
     XMLUnit.setCompareUnmatched(false);
   }
 
-  @BeforeClass
-  public static void setClientInstances() {
-    v4Client = ODataClientFactory.getClient();
-  }
-
   protected String getSuffix(final ContentType contentType) {
     return contentType.isCompatible(ContentType.APPLICATION_ATOM_SVC)
         || contentType.isCompatible(ContentType.APPLICATION_ATOM_XML)

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/lib/client-core/src/test/java/org/apache/olingo/client/core/AtomTest.java
----------------------------------------------------------------------
diff --git a/lib/client-core/src/test/java/org/apache/olingo/client/core/AtomTest.java b/lib/client-core/src/test/java/org/apache/olingo/client/core/AtomTest.java
index 9d5346b..ba20144 100644
--- a/lib/client-core/src/test/java/org/apache/olingo/client/core/AtomTest.java
+++ b/lib/client-core/src/test/java/org/apache/olingo/client/core/AtomTest.java
@@ -30,18 +30,12 @@ import javax.xml.transform.stream.StreamResult;
 import javax.xml.transform.stream.StreamSource;
 
 import org.apache.commons.io.IOUtils;
-import org.apache.olingo.client.api.ODataClient;
 import org.apache.olingo.commons.api.format.ContentType;
 import org.custommonkey.xmlunit.Diff;
 
 public class AtomTest extends JSONTest {
 
   @Override
-  protected ODataClient getClient() {
-    return v4Client;
-  }
-
-  @Override
   protected ContentType getODataPubFormat() {
     return ContentType.APPLICATION_ATOM_XML;
   }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/lib/client-core/src/test/java/org/apache/olingo/client/core/EntitySetTest.java
----------------------------------------------------------------------
diff --git a/lib/client-core/src/test/java/org/apache/olingo/client/core/EntitySetTest.java b/lib/client-core/src/test/java/org/apache/olingo/client/core/EntitySetTest.java
index 199cd05..254e83f 100644
--- a/lib/client-core/src/test/java/org/apache/olingo/client/core/EntitySetTest.java
+++ b/lib/client-core/src/test/java/org/apache/olingo/client/core/EntitySetTest.java
@@ -26,7 +26,6 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.net.URI;
 
-import org.apache.olingo.client.api.ODataClient;
 import org.apache.olingo.client.api.data.ResWrap;
 import org.apache.olingo.client.api.domain.ClientEntity;
 import org.apache.olingo.client.api.domain.ClientEntitySet;
@@ -37,23 +36,18 @@ import org.junit.Test;
 
 public class EntitySetTest extends AbstractTest {
 
-  @Override
-  protected ODataClient getClient() {
-    return v4Client;
-  }
-
   private void read(final ContentType contentType) throws IOException, ODataDeserializerException {
     final InputStream input = getClass().getResourceAsStream("Customers." + getSuffix(contentType));
-    final ClientEntitySet entitySet = getClient().getBinder().getODataEntitySet(
-        getClient().getDeserializer(contentType).toEntitySet(input));
+    final ClientEntitySet entitySet = client.getBinder().getODataEntitySet(
+        client.getDeserializer(contentType).toEntitySet(input));
     assertNotNull(entitySet);
 
     assertEquals(2, entitySet.getEntities().size());
     assertNull(entitySet.getNext());
 
     final ClientEntitySet written =
-        getClient().getBinder().getODataEntitySet(new ResWrap<EntityCollection>((URI) null, null,
-            getClient().getBinder().getEntitySet(entitySet)));
+        client.getBinder().getODataEntitySet(new ResWrap<EntityCollection>((URI) null, null,
+            client.getBinder().getEntitySet(entitySet)));
     assertEquals(entitySet, written);
   }
 
@@ -69,8 +63,8 @@ public class EntitySetTest extends AbstractTest {
 
   private void ref(final ContentType contentType) throws ODataDeserializerException {
     final InputStream input = getClass().getResourceAsStream("collectionOfEntityReferences." + getSuffix(contentType));
-    final ClientEntitySet entitySet = getClient().getBinder().getODataEntitySet(
-        getClient().getDeserializer(contentType).toEntitySet(input));
+    final ClientEntitySet entitySet = client.getBinder().getODataEntitySet(
+        client.getDeserializer(contentType).toEntitySet(input));
     assertNotNull(entitySet);
 
     for (ClientEntity entity : entitySet.getEntities()) {
@@ -79,8 +73,8 @@ public class EntitySetTest extends AbstractTest {
     entitySet.setCount(entitySet.getEntities().size());
 
     final ClientEntitySet written =
-        getClient().getBinder().getODataEntitySet(new ResWrap<EntityCollection>((URI) null, null,
-            getClient().getBinder().getEntitySet(entitySet)));
+        client.getBinder().getODataEntitySet(new ResWrap<EntityCollection>((URI) null, null,
+            client.getBinder().getEntitySet(entitySet)));
     assertEquals(entitySet, written);
   }
 


[13/22] olingo-odata4 git commit: OLINGO-861, OLINGO-863, OLINGO-868, OLINGO-869 : Improvements to MetadataParser for annotation support

Posted by mi...@apache.org.
OLINGO-861, OLINGO-863, OLINGO-868, OLINGO-869 : Improvements to MetadataParser for annotation support


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

Branch: refs/heads/OLINGO-832_StreamSerializerPoC
Commit: 6d94f0e386b7f3126f1023c87c78670fb55e2d5a
Parents: b317b90
Author: Ramesh Reddy <ra...@jboss.org>
Authored: Sat Feb 6 13:31:26 2016 -0600
Committer: Ramesh Reddy <ra...@jboss.org>
Committed: Sat Feb 6 13:31:26 2016 -0600

----------------------------------------------------------------------
 .../commons/api/edm/provider/CsdlOnDelete.java  |  23 +-
 .../api/edm/provider/CsdlReturnType.java        |  23 +-
 .../olingo/server/api/edmx/EdmxReference.java   |  24 +-
 .../olingo/server/core/MetadataParser.java      | 498 ++++++++++--
 .../core/MetadataParserAnnotationsTest.java     | 208 +++++
 .../olingo/server/core/MetadataParserTest.java  |   3 +-
 .../server/core/ServiceDispatcherTest.java      |  17 +-
 .../olingo/server/example/TripPinServlet.java   |   9 +-
 .../src/test/resources/annotations.xml          | 153 ++++
 .../src/test/resources/trippin.xml              | 808 +++++++++++--------
 10 files changed, 1311 insertions(+), 455 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/6d94f0e3/lib/commons-api/src/main/java/org/apache/olingo/commons/api/edm/provider/CsdlOnDelete.java
----------------------------------------------------------------------
diff --git a/lib/commons-api/src/main/java/org/apache/olingo/commons/api/edm/provider/CsdlOnDelete.java b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/edm/provider/CsdlOnDelete.java
index 1a326dd..e3ed711 100644
--- a/lib/commons-api/src/main/java/org/apache/olingo/commons/api/edm/provider/CsdlOnDelete.java
+++ b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/edm/provider/CsdlOnDelete.java
@@ -18,13 +18,17 @@
  */
 package org.apache.olingo.commons.api.edm.provider;
 
+import java.util.ArrayList;
+import java.util.List;
+
 /**
  * The type Csdl on delete.
  */
-public class CsdlOnDelete extends CsdlAbstractEdmItem {
+public class CsdlOnDelete extends CsdlAbstractEdmItem implements CsdlAnnotatable {
 
   private CsdlOnDeleteAction action = CsdlOnDeleteAction.None;
-
+  
+  private List<CsdlAnnotation> annotations = new ArrayList<CsdlAnnotation>();
   /**
    * Gets action.
    *
@@ -45,4 +49,19 @@ public class CsdlOnDelete extends CsdlAbstractEdmItem {
     return this;
   }
 
+  @Override
+  public List<CsdlAnnotation> getAnnotations() {
+    return annotations;
+  }
+
+  /**
+   * Sets annotations.
+   *
+   * @param annotations the annotations
+   * @return the annotations
+   */
+  public CsdlOnDelete setAnnotations(final List<CsdlAnnotation> annotations) {
+    this.annotations = annotations;
+    return this;
+  }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/6d94f0e3/lib/commons-api/src/main/java/org/apache/olingo/commons/api/edm/provider/CsdlReturnType.java
----------------------------------------------------------------------
diff --git a/lib/commons-api/src/main/java/org/apache/olingo/commons/api/edm/provider/CsdlReturnType.java b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/edm/provider/CsdlReturnType.java
index eb94acc..e5cee4e 100644
--- a/lib/commons-api/src/main/java/org/apache/olingo/commons/api/edm/provider/CsdlReturnType.java
+++ b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/edm/provider/CsdlReturnType.java
@@ -18,13 +18,16 @@
  */
 package org.apache.olingo.commons.api.edm.provider;
 
+import java.util.ArrayList;
+import java.util.List;
+
 import org.apache.olingo.commons.api.edm.FullQualifiedName;
 import org.apache.olingo.commons.api.edm.geo.SRID;
 
 /**
  * The type Csdl return type.
  */
-public class CsdlReturnType extends CsdlAbstractEdmItem {
+public class CsdlReturnType extends CsdlAbstractEdmItem implements CsdlAnnotatable {
 
   private String type;
 
@@ -40,6 +43,8 @@ public class CsdlReturnType extends CsdlAbstractEdmItem {
   private Integer scale;
 
   private SRID srid;
+  
+  private List<CsdlAnnotation> annotations = new ArrayList<CsdlAnnotation>();
 
   /**
    * Gets type.
@@ -200,4 +205,20 @@ public class CsdlReturnType extends CsdlAbstractEdmItem {
     this.srid = srid;
     return this;
   }
+
+  @Override
+  public List<CsdlAnnotation> getAnnotations() {
+    return annotations;
+  }
+
+  /**
+   * Sets annotations.
+   *
+   * @param annotations the annotations
+   * @return the annotations
+   */
+  public CsdlReturnType setAnnotations(final List<CsdlAnnotation> annotations) {
+    this.annotations = annotations;
+    return this;
+  }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/6d94f0e3/lib/commons-api/src/main/java/org/apache/olingo/server/api/edmx/EdmxReference.java
----------------------------------------------------------------------
diff --git a/lib/commons-api/src/main/java/org/apache/olingo/server/api/edmx/EdmxReference.java b/lib/commons-api/src/main/java/org/apache/olingo/server/api/edmx/EdmxReference.java
index 38d17fe..e1b735b 100644
--- a/lib/commons-api/src/main/java/org/apache/olingo/server/api/edmx/EdmxReference.java
+++ b/lib/commons-api/src/main/java/org/apache/olingo/server/api/edmx/EdmxReference.java
@@ -23,15 +23,19 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
+import org.apache.olingo.commons.api.edm.provider.CsdlAnnotatable;
+import org.apache.olingo.commons.api.edm.provider.CsdlAnnotation;
+import org.apache.olingo.commons.api.edm.provider.CsdlReturnType;
+
 /**
  * POJO for Edmx Reference.
  */
-public class EdmxReference {
+public class EdmxReference implements CsdlAnnotatable{
 
   private final URI uri;
   private final List<EdmxReferenceInclude> edmxIncludes;
   private final List<EdmxReferenceIncludeAnnotation> edmxIncludeAnnotations;
-
+  private List<CsdlAnnotation> annotations = new ArrayList<CsdlAnnotation>();
   /**
    * Create reference with given uri
    *
@@ -90,4 +94,20 @@ public class EdmxReference {
     edmxIncludeAnnotations.add(includeAnnotation);
     return this;
   }
+  
+  @Override
+  public List<CsdlAnnotation> getAnnotations() {
+    return annotations;
+  }
+
+  /**
+   * Sets annotations.
+   *
+   * @param annotations the annotations
+   * @return the annotations
+   */
+  public EdmxReference setAnnotations(final List<CsdlAnnotation> annotations) {
+    this.annotations = annotations;
+    return this;
+  }  
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/6d94f0e3/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/MetadataParser.java
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/MetadataParser.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/MetadataParser.java
index b5ffd4a..e8122d7 100644
--- a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/MetadataParser.java
+++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/MetadataParser.java
@@ -19,9 +19,10 @@
 package org.apache.olingo.server.core;
 
 import java.io.Reader;
+import java.net.URI;
+import java.net.URISyntaxException;
 import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
+import java.util.Arrays;
 
 import javax.xml.namespace.QName;
 import javax.xml.stream.XMLEventReader;
@@ -36,6 +37,10 @@ import org.apache.olingo.commons.api.edm.FullQualifiedName;
 import org.apache.olingo.commons.api.edm.geo.SRID;
 import org.apache.olingo.commons.api.edm.provider.CsdlAction;
 import org.apache.olingo.commons.api.edm.provider.CsdlActionImport;
+import org.apache.olingo.commons.api.edm.provider.CsdlAnnotatable;
+import org.apache.olingo.commons.api.edm.provider.CsdlAnnotation;
+import org.apache.olingo.commons.api.edm.provider.CsdlAnnotations;
+import org.apache.olingo.commons.api.edm.provider.CsdlBindingTarget;
 import org.apache.olingo.commons.api.edm.provider.CsdlComplexType;
 import org.apache.olingo.commons.api.edm.provider.CsdlEdmProvider;
 import org.apache.olingo.commons.api.edm.provider.CsdlEntityContainer;
@@ -59,33 +64,91 @@ import org.apache.olingo.commons.api.edm.provider.CsdlSchema;
 import org.apache.olingo.commons.api.edm.provider.CsdlSingleton;
 import org.apache.olingo.commons.api.edm.provider.CsdlTerm;
 import org.apache.olingo.commons.api.edm.provider.CsdlTypeDefinition;
+import org.apache.olingo.commons.api.edm.provider.annotation.CsdlAnnotationPath;
+import org.apache.olingo.commons.api.edm.provider.annotation.CsdlApply;
+import org.apache.olingo.commons.api.edm.provider.annotation.CsdlCast;
+import org.apache.olingo.commons.api.edm.provider.annotation.CsdlCollection;
+import org.apache.olingo.commons.api.edm.provider.annotation.CsdlConstantExpression;
+import org.apache.olingo.commons.api.edm.provider.annotation.CsdlConstantExpression.ConstantExpressionType;
+import org.apache.olingo.commons.api.edm.provider.annotation.CsdlExpression;
+import org.apache.olingo.commons.api.edm.provider.annotation.CsdlIf;
+import org.apache.olingo.commons.api.edm.provider.annotation.CsdlIsOf;
+import org.apache.olingo.commons.api.edm.provider.annotation.CsdlLabeledElement;
+import org.apache.olingo.commons.api.edm.provider.annotation.CsdlLabeledElementReference;
+import org.apache.olingo.commons.api.edm.provider.annotation.CsdlNavigationPropertyPath;
+import org.apache.olingo.commons.api.edm.provider.annotation.CsdlNull;
+import org.apache.olingo.commons.api.edm.provider.annotation.CsdlPath;
+import org.apache.olingo.commons.api.edm.provider.annotation.CsdlPropertyPath;
+import org.apache.olingo.commons.api.edm.provider.annotation.CsdlPropertyValue;
+import org.apache.olingo.commons.api.edm.provider.annotation.CsdlRecord;
+import org.apache.olingo.commons.api.edm.provider.annotation.CsdlUrlRef;
+import org.apache.olingo.server.api.ServiceMetadata;
+import org.apache.olingo.server.api.edmx.EdmxReference;
+import org.apache.olingo.server.api.edmx.EdmxReferenceInclude;
+import org.apache.olingo.server.api.edmx.EdmxReferenceIncludeAnnotation;
 
 /**
  * This class can convert a CSDL document into EDMProvider object
  */
 public class MetadataParser {
+  private boolean parseAnnotations = false;
 
-  public CsdlEdmProvider buildEdmProvider(Reader csdl) throws XMLStreamException {
+  public void setParseAnnotations(boolean f) {
+    this.parseAnnotations = true;
+  }
+  
+  public ServiceMetadata buildServiceMetadata(Reader csdl) throws XMLStreamException {
     XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
     XMLEventReader reader = xmlInputFactory.createXMLEventReader(csdl);
 
     SchemaBasedEdmProvider provider = new SchemaBasedEdmProvider();
+    final ArrayList<EdmxReference> references = new ArrayList<EdmxReference>();
+    
     new ElementReader<SchemaBasedEdmProvider>() {
       @Override
       void build(XMLEventReader reader, StartElement element, SchemaBasedEdmProvider provider,
           String name) throws XMLStreamException {
         String version = attr(element, "Version");
         if ("4.0".equals(version)) {
-          readDataServicesAndReference(reader, element, provider);
+          readDataServicesAndReference(reader, element, provider, references);
+        } else {
+          throw new XMLStreamException("Currently only V4 is supported.");
         }
       }
     }.read(reader, null, provider, "Edmx");
-
-    return provider;
+    if(reader.hasNext()) {
+      XMLEvent event = reader.peek();
+      throw new XMLStreamException(
+          "Failed to read complete metadata file. Failed at "
+              + (event.isStartElement() ? 
+                  event.asStartElement().getName().getLocalPart() : 
+                  event.asEndElement().getName().getLocalPart()));
+    }
+    return new ServiceMetadataImpl(provider, references, null);
   }
 
-  private void readDataServicesAndReference(XMLEventReader reader, StartElement element,
-      SchemaBasedEdmProvider provider) throws XMLStreamException {
+  CsdlEdmProvider buildEdmProvider(Reader csdl) throws XMLStreamException {
+    XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
+    XMLEventReader reader = xmlInputFactory.createXMLEventReader(csdl);
+
+    SchemaBasedEdmProvider provider = new SchemaBasedEdmProvider();
+    new ElementReader<SchemaBasedEdmProvider>() {
+      @Override
+      void build(XMLEventReader reader, StartElement element, SchemaBasedEdmProvider provider,
+          String name) throws XMLStreamException {
+        String version = attr(element, "Version");
+        if ("4.0".equals(version)) {
+          readDataServicesAndReference(reader, element, provider, new ArrayList<EdmxReference>());
+        }
+      }
+    }.read(reader, null, provider, "Edmx");
+
+    return provider;
+  }  
+  
+  private void readDataServicesAndReference(XMLEventReader reader,
+      StartElement element, SchemaBasedEdmProvider provider,
+      final ArrayList<EdmxReference> references) throws XMLStreamException {
     new ElementReader<SchemaBasedEdmProvider>() {
       @Override
       void build(XMLEventReader reader, StartElement element, SchemaBasedEdmProvider provider,
@@ -93,45 +156,64 @@ public class MetadataParser {
         if (name.equals("DataServices")) {
           readSchema(reader, element, provider);
         } else if (name.equals("Reference")) {
-          readReference(reader, element, provider, "Reference");
+          readReference(reader, element, references, "Reference");
         }
       }
     }.read(reader, element, provider, "DataServices", "Reference");
   }
 
   private void readReference(XMLEventReader reader, StartElement element,
-      SchemaBasedEdmProvider provider, String name) throws XMLStreamException {
-    new ElementReader<SchemaBasedEdmProvider>() {
+      final ArrayList<EdmxReference> references, String name) throws XMLStreamException {
+    EdmxReference reference;
+    try {
+      String uri = attr(element, "Uri");
+      reference = new EdmxReference(new URI(uri));
+    } catch (URISyntaxException e) {
+      throw new XMLStreamException(e);
+    }
+    new ElementReader<EdmxReference>() {
       @Override
-      void build(XMLEventReader reader, StartElement element, SchemaBasedEdmProvider t, String name)
-          throws XMLStreamException {
-        // TODO:
+      void build(XMLEventReader reader, StartElement element,
+          EdmxReference reference, String name) throws XMLStreamException {
+        if (name.equals("Include")) {
+          EdmxReferenceInclude include = new EdmxReferenceInclude(attr(element, "Namespace"),
+              attr(element, "Alias"));
+          reference.addInclude(include);
+        } else if (name.equals("IncludeAnnotations")) {
+          EdmxReferenceIncludeAnnotation annotation = new EdmxReferenceIncludeAnnotation(
+              attr(element, "TermNamespace"));
+          annotation.setTargetNamespace(attr(element, "TargetNamespace"));
+          annotation.setQualifier(attr(element, "Qualifier"));
+          reference.addIncludeAnnotation(annotation);
+        } else if (name.equals("Annotation")) {
+          readAnnotations(reader, element, reference);
+        }
       }
-    }.read(reader, element, provider, name);
+    }.read(reader, element, reference, "Include", "IncludeAnnotations", "Annotation");
+    references.add(reference);
   }
-
+  
   private void readSchema(XMLEventReader reader, StartElement element,
       SchemaBasedEdmProvider provider) throws XMLStreamException {
 
-    CsdlSchema schema = new CsdlSchema();
-    schema.setComplexTypes(new ArrayList<CsdlComplexType>());
-    schema.setActions(new ArrayList<CsdlAction>());
-    schema.setEntityTypes(new ArrayList<CsdlEntityType>());
-    schema.setEnumTypes(new ArrayList<CsdlEnumType>());
-    schema.setFunctions(new ArrayList<CsdlFunction>());
-    schema.setTerms(new ArrayList<CsdlTerm>());
-    schema.setTypeDefinitions(new ArrayList<CsdlTypeDefinition>());
-
-    new ElementReader<CsdlSchema>() {
+    new ElementReader<SchemaBasedEdmProvider>() {
       @Override
-      void build(XMLEventReader reader, StartElement element, CsdlSchema schema, String name)
+      void build(XMLEventReader reader, StartElement element, SchemaBasedEdmProvider provider, String name)
           throws XMLStreamException {
+        CsdlSchema schema = new CsdlSchema();
+        schema.setComplexTypes(new ArrayList<CsdlComplexType>());
+        schema.setActions(new ArrayList<CsdlAction>());
+        schema.setEntityTypes(new ArrayList<CsdlEntityType>());
+        schema.setEnumTypes(new ArrayList<CsdlEnumType>());
+        schema.setFunctions(new ArrayList<CsdlFunction>());
+        schema.setTerms(new ArrayList<CsdlTerm>());
+        schema.setTypeDefinitions(new ArrayList<CsdlTypeDefinition>());        
         schema.setNamespace(attr(element, "Namespace"));
         schema.setAlias(attr(element, "Alias"));
         readSchemaContents(reader, schema);
+        provider.addSchema(schema);
       }
-    }.read(reader, element, schema, "Schema");
-    provider.addSchema(schema);
+    }.read(reader, element, provider, "Schema");
   }
 
   private void readSchemaContents(XMLEventReader reader, CsdlSchema schema) throws XMLStreamException {
@@ -141,9 +223,10 @@ public class MetadataParser {
           throws XMLStreamException {
         if (name.equals("Action")) {
           readAction(reader, element, schema);
-//        } else if (name.equals("Annotations")) {
-//        } else if (name.equals("Annotation")) {
-          // TODO: Add support for annotations
+        } else if (name.equals("Annotations")) {
+          readAnnotationGroup(reader, element, schema);
+        } else if (name.equals("Annotation")) {
+          readAnnotations(reader, element, schema);
         } else if (name.equals("ComplexType")) {
           readComplexType(reader, element, schema);
         } else if (name.equals("EntityContainer")) {
@@ -155,9 +238,9 @@ public class MetadataParser {
         } else if (name.equals("Function")) {
           readFunction(reader, element, schema);
         } else if (name.equals("Term")) {
-          schema.getTerms().add(readTerm(element));
+          schema.getTerms().add(readTerm(reader, element));
         } else if (name.equals("TypeDefinition")) {
-          schema.getTypeDefinitions().add(readTypeDefinition(element));
+          schema.getTypeDefinitions().add(readTypeDefinition(reader, element));
         }
       }
     }.read(reader, null, schema, "Action", "Annotations", "Annotation", "ComplexType",
@@ -196,7 +279,8 @@ public class MetadataParser {
     return false;
   }
 
-  private void readReturnType(StartElement element, CsdlOperation operation) {
+  private void readReturnType(XMLEventReader reader, StartElement element,
+      CsdlOperation operation) throws XMLStreamException {
     CsdlReturnType returnType = new CsdlReturnType();
     returnType.setType(readType(element));
     returnType.setCollection(isCollectionType(element));
@@ -216,13 +300,14 @@ public class MetadataParser {
     }
     String srid = attr(element, "SRID");
     if (srid != null) {
-      // TODO: no olingo support yet.
       returnType.setSrid(SRID.valueOf(srid));
     }
+    peekAnnotations(reader, element.getName().getLocalPart(), returnType);
     operation.setReturnType(returnType);
   }
 
-  private void readParameter(StartElement element, CsdlOperation operation) {
+  private void readParameter(XMLEventReader reader, StartElement element,
+      CsdlOperation operation) throws XMLStreamException {
     CsdlParameter parameter = new CsdlParameter();
     parameter.setName(attr(element, "Name"));
     parameter.setType(readType(element));
@@ -243,13 +328,14 @@ public class MetadataParser {
     }
     String srid = attr(element, "SRID");
     if (srid != null) {
-      // TODO: no olingo support yet.
       parameter.setSrid(SRID.valueOf(srid));
     }
+    peekAnnotations(reader, element.getName().getLocalPart(), parameter);
     operation.getParameters().add(parameter);
   }
 
-  private CsdlTypeDefinition readTypeDefinition(StartElement element) {
+  private CsdlTypeDefinition readTypeDefinition(XMLEventReader reader,
+      StartElement element) throws XMLStreamException {
     CsdlTypeDefinition td = new CsdlTypeDefinition();
     td.setName(attr(element, "Name"));
     td.setUnderlyingType(new FullQualifiedName(attr(element, "UnderlyingType")));
@@ -269,16 +355,17 @@ public class MetadataParser {
     }
     String srid = attr(element, "SRID");
     if (srid != null) {
-      // TODO: no olingo support yet.
       td.setSrid(SRID.valueOf(srid));
     }
+    peekAnnotations(reader, element.getName().getLocalPart(), td);
     return td;
   }
 
-  private CsdlTerm readTerm(StartElement element) {
+  private CsdlTerm readTerm(XMLEventReader reader, StartElement element) throws XMLStreamException {
     CsdlTerm term = new CsdlTerm();
     term.setName(attr(element, "Name"));
     term.setType(attr(element, "Type"));
+    
     if (attr(element, "BaseTerm") != null) {
       term.setBaseTerm(attr(element, "BaseTerm"));
     }
@@ -286,7 +373,8 @@ public class MetadataParser {
       term.setDefaultValue(attr(element, "DefaultValue"));
     }
     if (attr(element, "AppliesTo") != null) {
-      term.setAppliesTo(Collections.singletonList(attr(element, "AppliesTo")));
+      String[] appliesTo = attr(element, "AppliesTo").split("\\s+");
+      term.setAppliesTo(Arrays.asList(appliesTo));
     }
     term.setNullable(Boolean.parseBoolean(attr(element, "Nullable")));
     String maxLength = attr(element, "MaxLength");
@@ -303,12 +391,231 @@ public class MetadataParser {
     }
     String srid = attr(element, "SRID");
     if (srid != null) {
-      // TODO: no olingo support yet.
       term.setSrid(SRID.valueOf(srid));
     }
+    peekAnnotations(reader, "Term", term);
     return term;
   }
 
+  private void readAnnotationGroup(XMLEventReader reader, StartElement element,
+      CsdlSchema schema) throws XMLStreamException {
+    final CsdlAnnotations annotations = new CsdlAnnotations();
+    annotations.setTarget(attr(element, "Target"));
+    annotations.setQualifier(attr(element, "Qualifier"));
+    readAnnotations(reader, element, annotations);
+    schema.getAnnotationGroups().add(annotations);
+  }
+
+  private void peekAnnotations(XMLEventReader reader, String endName,
+      CsdlAnnotatable edmObject) throws XMLStreamException {
+    if(!parseAnnotations) {
+      return;
+    }
+    while (reader.hasNext()) {
+      XMLEvent event = reader.peek();
+
+      if (!event.isStartElement() && !event.isEndElement()) {
+        reader.nextEvent();
+        continue;
+      }
+      
+      if (event.isStartElement()) {
+        StartElement element = event.asStartElement();
+        if (element.getName().getLocalPart().equals("Annotation")) {
+          reader.nextEvent();
+          readAnnotations(reader, element, edmObject);
+        }
+      }
+      
+      if (event.isEndElement()) {
+        EndElement element = event.asEndElement();
+        if (element.getName().getLocalPart().equals("Annotation")) {
+          reader.nextEvent();
+        }
+        
+        if (element.getName().getLocalPart().equals(endName)) {
+          return;
+        }
+      }
+    }
+  }
+  
+  private void readAnnotations(XMLEventReader reader, StartElement element,
+      CsdlAnnotatable edmObject) throws XMLStreamException {
+    if (!parseAnnotations) {
+      return;
+    }
+    final CsdlAnnotation annotation = new CsdlAnnotation();
+    annotation.setTerm(attr(element, "Term"));
+    for (ConstantExpressionType type:ConstantExpressionType.values()) {
+      if (attr(element, type.name()) != null) {
+        annotation.setExpression(new CsdlConstantExpression(
+            type, attr(element, type.name())));
+      }        
+    }
+    readExpressions(reader, element, annotation);
+    edmObject.getAnnotations().add(annotation);
+  } 
+
+  private <T> void write(T t, CsdlExpression expr) throws XMLStreamException {
+    if(t instanceof CsdlAnnotation) {
+      ((CsdlAnnotation)t).setExpression(expr);
+    } else if (t instanceof CsdlUrlRef) {
+      ((CsdlUrlRef)t).setValue(expr);
+    } else if (t instanceof CsdlCast) {
+      ((CsdlCast)t).setValue(expr);
+    } else if (t instanceof CsdlLabeledElement) {
+      ((CsdlLabeledElement)t).setValue(expr);
+    } else if (t instanceof CsdlIsOf) {
+      ((CsdlIsOf)t).setValue(expr);
+    } else if (t instanceof CsdlCollection) {
+      ((CsdlCollection)t).getItems().add(((CsdlCollection)t).getItems().size(), expr);
+    } else if (t instanceof CsdlApply) {
+      ((CsdlApply)t).getParameters().add(expr);
+    } else if (t instanceof CsdlIf) {
+      if (((CsdlIf)t).getGuard() == null) {
+        ((CsdlIf)t).setGuard(expr);
+      } else if (((CsdlIf)t).getThen() == null) {
+        ((CsdlIf)t).setThen(expr);
+      } else {
+        ((CsdlIf)t).setElse(expr);
+      }
+    } else if (t instanceof CsdlPropertyValue) {
+      ((CsdlPropertyValue)t).setValue(expr);
+    } else {
+      throw new XMLStreamException("Unknown expression parent in Annoatation");
+    }
+  }
+  
+  private <T> void readExpressions(XMLEventReader reader,
+      StartElement element, T target)
+      throws XMLStreamException {
+    new ElementReader<T>() {
+      @Override
+      void build(XMLEventReader reader, StartElement element, T target, String name)
+          throws XMLStreamException {
+        
+        // attribute based expressions        
+        if (attr(element,  "AnnotationPath") != null) {
+         write(target, new CsdlAnnotationPath().setValue(attr(element,  "AnnotationPath"))); 
+        }
+        if (attr(element,  "NavigationPropertyPath") != null) {
+          write(target, new CsdlNavigationPropertyPath()
+              .setValue(attr(element, "NavigationPropertyPath"))); 
+        }
+        if (attr(element,  "Path") != null) {
+          write(target, new CsdlPath().setValue(attr(element, "Path"))); 
+        }
+        if (attr(element,  "PropertyPath") != null) {
+          write(target, new CsdlPropertyPath().setValue(attr(element, "PropertyPath"))); 
+        }
+        if (attr(element,  "UrlRef") != null) {
+          write(target, new CsdlUrlRef().setValue(new CsdlConstantExpression(
+              ConstantExpressionType.String, attr(element, "UrlRef"))));
+        }        
+
+        // element based expressions
+        for (ConstantExpressionType type:ConstantExpressionType.values()) {
+          if (name.equals(type.name())) {
+            if (reader.peek().isCharacters()) {
+              CsdlExpression expr = new CsdlConstantExpression(type, elementValue(reader, element));
+              write(target, expr);
+            }
+          }        
+        }        
+        if (name.equals("Collection")) {
+          CsdlCollection expr = new CsdlCollection();
+          readExpressions(reader, element, expr);
+          write(target, expr);
+        } else if (name.equals("AnnotationPath")) {
+          write(target, new CsdlAnnotationPath().setValue(elementValue(reader, element)));
+        } else if (name.equals("NavigationPropertyPath")) {
+          write(target, new CsdlNavigationPropertyPath()
+              .setValue(elementValue(reader, element)));
+        } else if (name.equals("Path")) {
+          write(target, new CsdlPath().setValue(elementValue(reader, element)));
+        } else if (name.equals("PropertyPath")) {
+          write(target, new CsdlPropertyPath().setValue(elementValue(reader, element)));
+        } else if (name.equals("UrlRef")) {
+          CsdlUrlRef expr = new CsdlUrlRef();
+          readExpressions(reader, element, expr);
+          write(target, expr);
+        } else if (name.equals("Apply")) {
+          CsdlApply expr = new CsdlApply();
+          expr.setFunction(attr(element, "Function"));
+          readExpressions(reader, element, expr);
+          write(target, expr);
+        } else if (name.equals("Cast")) {
+          CsdlCast expr = new CsdlCast();
+          expr.setType(attr(element, "Type"));
+          readExpressions(reader, element, expr);
+          write(target, expr);
+        } else if (name.equals("If")) {
+          CsdlIf expr = new CsdlIf();
+          readExpressions(reader, element, expr);
+          write(target, expr);
+        } else if (name.equals("IsOf")) {
+          CsdlIsOf expr = new CsdlIsOf();
+          expr.setType(attr(element, "Type"));
+          readExpressions(reader, element, expr);
+          write(target, expr);
+        } else if (name.equals("LabeledElement")) {
+          CsdlLabeledElement expr = new CsdlLabeledElement();
+          expr.setName(attr(element, "Name"));
+          readExpressions(reader, element, expr);
+          write(target, expr);
+        } else if (name.equals("LabeledElementReference")) {
+          CsdlLabeledElementReference expr = new CsdlLabeledElementReference();
+          expr.setValue(elementValue(reader, element));
+          write(target, expr);
+        } else if (name.equals("Null")) {
+          write(target, new CsdlNull());
+        } else if (name.equals("Record")) {
+          CsdlRecord expr = new CsdlRecord();
+          expr.setType(attr(element, "Type"));          
+          readPropertyValues(reader, element, expr);
+          write(target, expr);          
+        }
+      }
+    }.read(reader, element, target, "Collection", "AnnotationPath",
+        "NavigationPropertyPath", "Path", "PropertyPath", "UrlRef",
+        "Apply", "Function", "Cast", "If", "IsOf", "LabeledElement",
+        "LabeledElementReference", "Null", "Record","Binary", "Bool", "Date",
+        "DateTimeOffset", "Decimal", "Duration", "EnumMember", "Float", "Guid",
+        "Int", "String", "TimeOfDay");
+  }
+  
+  private String elementValue(XMLEventReader reader, StartElement element) throws XMLStreamException {
+    while (reader.hasNext()) {
+      XMLEvent event = reader.peek();
+      if (event.isStartElement() || event.isEndElement()) {
+        return null;
+      } else if (event.isCharacters()){
+        reader.nextEvent();
+        String data = event.asCharacters().getData();
+        if (data.trim().length() > 0) {
+          return data.trim();
+        }
+      }
+    }    
+    return null;
+  }
+  
+  private void readPropertyValues(XMLEventReader reader,
+      StartElement element, CsdlRecord record) throws XMLStreamException {
+    
+    new ElementReader<CsdlRecord>() {
+      @Override
+      void build(XMLEventReader reader, StartElement element, CsdlRecord record, String name)
+          throws XMLStreamException {
+        CsdlPropertyValue value = new CsdlPropertyValue();
+        value.setProperty(attr(element, "Property"));
+        readExpressions(reader, element, value);
+        record.getPropertyValues().add(value);
+      }
+    }.read(reader, element, record, "PropertyValue");    
+  }  
+  
   private void readFunction(XMLEventReader reader, StartElement element, CsdlSchema schema)
       throws XMLStreamException {
     CsdlFunction function = new CsdlFunction();
@@ -332,12 +639,14 @@ public class MetadataParser {
       void build(XMLEventReader reader, StartElement element, CsdlOperation operation, String name)
           throws XMLStreamException {
         if (name.equals("Parameter")) {
-          readParameter(element, operation);
+          readParameter(reader, element, operation);
         } else if (name.equals("ReturnType")) {
-          readReturnType(element, operation);
+          readReturnType(reader, element, operation);
+        } else if (name.equals("Annotation")) {
+          readAnnotations(reader, element, operation);
         }
       }
-    }.read(reader, null, operation, "Parameter", "ReturnType");
+    }.read(reader, null, operation, "Parameter", "ReturnType", "Annotation");
   }
 
   private void readEnumType(XMLEventReader reader, StartElement element, CsdlSchema schema)
@@ -356,16 +665,22 @@ public class MetadataParser {
 
   private void readEnumMembers(XMLEventReader reader, StartElement element, CsdlEnumType type)
       throws XMLStreamException {
+    
     new ElementReader<CsdlEnumType>() {
       @Override
       void build(XMLEventReader reader, StartElement element, CsdlEnumType type, String name)
           throws XMLStreamException {
-        CsdlEnumMember member = new CsdlEnumMember();
-        member.setName(attr(element, "Name"));
-        member.setValue(attr(element, "Value"));
-        type.getMembers().add(member);
+        if (name.equals("Member")) {
+          CsdlEnumMember member = new CsdlEnumMember();
+          member.setName(attr(element, "Name"));
+          member.setValue(attr(element, "Value"));
+          peekAnnotations(reader, name, member);
+          type.getMembers().add(member);
+        } else if (name.equals("Annotation")) {
+          readAnnotations(reader, element, type);
+        }
       }
-    }.read(reader, element, type, "Member");
+    }.read(reader, element, type, "Member", "Annotation");
   }
 
   private void readEntityType(XMLEventReader reader, StartElement element, CsdlSchema schema)
@@ -392,14 +707,16 @@ public class MetadataParser {
       void build(XMLEventReader reader, StartElement element, CsdlEntityType entityType, String name)
           throws XMLStreamException {
         if (name.equals("Property")) {
-          entityType.getProperties().add(readProperty(element));
+          entityType.getProperties().add(readProperty(reader, element));
         } else if (name.equals("NavigationProperty")) {
           entityType.getNavigationProperties().add(readNavigationProperty(reader, element));
         } else if (name.equals("Key")) {
           readKey(reader, element, entityType);
+        } else if (name.equals("Annotation")) {
+          readAnnotations(reader, element, entityType);
         }
       }
-    }.read(reader, null, entityType, "Property", "NavigationProperty", "Key");
+    }.read(reader, null, entityType, "Property", "NavigationProperty", "Key", "Annotation");
   }
 
   private void readKey(XMLEventReader reader, StartElement element, CsdlEntityType entityType)
@@ -436,12 +753,18 @@ public class MetadataParser {
           CsdlReferentialConstraint constraint = new CsdlReferentialConstraint();
           constraint.setProperty(attr(element, "Property"));
           constraint.setReferencedProperty(attr(element, "ReferencedProperty"));
+          peekAnnotations(reader, name, constraint);
           property.getReferentialConstraints().add(constraint);
         } else if (name.equals("OnDelete")) {
-          property.setOnDelete(new CsdlOnDelete().setAction(CsdlOnDeleteAction.valueOf(attr(element, "Action"))));
+          CsdlOnDelete delete = new CsdlOnDelete();
+          delete.setAction(CsdlOnDeleteAction.valueOf(attr(element, "Action")));
+          property.setOnDelete(delete);
+          peekAnnotations(reader, name, delete);
+        } else if (name.equals("Annotation")) {
+          readAnnotations(reader, element, property);
         }
       }
-    }.read(reader, element, property, "ReferentialConstraint", "OnDelete");
+    }.read(reader, element, property, "ReferentialConstraint", "OnDelete", "Annotation");
     return property;
   }
 
@@ -453,7 +776,8 @@ public class MetadataParser {
     return null;
   }
 
-  private CsdlProperty readProperty(StartElement element) {
+  private CsdlProperty readProperty(XMLEventReader reader, StartElement element)
+      throws XMLStreamException {
     CsdlProperty property = new CsdlProperty();
     property.setName(attr(element, "Name"));
     property.setType(readType(element));
@@ -476,13 +800,13 @@ public class MetadataParser {
     }
     String srid = attr(element, "SRID");
     if (srid != null) {
-      // TODO: no olingo support yet.
       property.setSrid(SRID.valueOf(srid));
     }
     String defaultValue = attr(element, "DefaultValue");
     if (defaultValue != null) {
       property.setDefaultValue(defaultValue);
     }
+    peekAnnotations(reader, element.getName().getLocalPart(), property);
     return property;
   }
 
@@ -507,13 +831,17 @@ public class MetadataParser {
         } else if (name.equals("Singleton")) {
           readSingleton(reader, element, container);
         } else if (name.equals("ActionImport")) {
-          readActionImport(element, container);
+          readActionImport(reader, element, container);
         } else if (name.equals("FunctionImport")) {
-          readFunctionImport(element, container);
+          readFunctionImport(reader, element, container);
+        } else if (name.equals("Annotation")) {
+          readAnnotations(reader, element, container);
         }
       }
 
-      private void readFunctionImport(StartElement element, CsdlEntityContainer container) {
+      private void readFunctionImport(XMLEventReader reader,
+          StartElement element, CsdlEntityContainer container)
+          throws XMLStreamException {
         CsdlFunctionImport functionImport = new CsdlFunctionImport();
         functionImport.setName(attr(element, "Name"));
         functionImport.setFunction(new FullQualifiedName(attr(element, "Function")));
@@ -524,10 +852,13 @@ public class MetadataParser {
         if (entitySet != null) {
           functionImport.setEntitySet(entitySet);
         }
+        peekAnnotations(reader, "FunctionImport", functionImport);
         container.getFunctionImports().add(functionImport);
       }
 
-      private void readActionImport(StartElement element, CsdlEntityContainer container) {
+      private void readActionImport(XMLEventReader reader,
+          StartElement element, CsdlEntityContainer container)
+          throws XMLStreamException {
         CsdlActionImport actionImport = new CsdlActionImport();
         actionImport.setName(attr(element, "Name"));
         actionImport.setAction(new FullQualifiedName(attr(element, "Action")));
@@ -536,6 +867,7 @@ public class MetadataParser {
         if (entitySet != null) {
           actionImport.setEntitySet(entitySet);
         }
+        peekAnnotations(reader, "ActionImport", actionImport);
         container.getActionImports().add(actionImport);
       }
 
@@ -546,7 +878,7 @@ public class MetadataParser {
         singleton.setName(attr(element, "Name"));
         singleton.setType(new FullQualifiedName(attr(element, "Type")));
         singleton.setNavigationPropertyBindings(new ArrayList<CsdlNavigationPropertyBinding>());
-        readNavigationPropertyBindings(reader, element, singleton.getNavigationPropertyBindings());
+        readNavigationPropertyBindings(reader, element, singleton);
         container.getSingletons().add(singleton);
       }
 
@@ -558,25 +890,29 @@ public class MetadataParser {
         entitySet.setIncludeInServiceDocument(Boolean.parseBoolean(attr(element,
             "IncludeInServiceDocument")));
         entitySet.setNavigationPropertyBindings(new ArrayList<CsdlNavigationPropertyBinding>());
-        readNavigationPropertyBindings(reader, element, entitySet.getNavigationPropertyBindings());
+        readNavigationPropertyBindings(reader, element, entitySet);
         container.getEntitySets().add(entitySet);
       }
 
       private void readNavigationPropertyBindings(XMLEventReader reader, StartElement element,
-          List<CsdlNavigationPropertyBinding> bindings) throws XMLStreamException {
-        new ElementReader<List<CsdlNavigationPropertyBinding>>() {
+          CsdlBindingTarget entitySet) throws XMLStreamException {
+        new ElementReader<CsdlBindingTarget>() {
           @Override
           void build(XMLEventReader reader, StartElement element,
-              List<CsdlNavigationPropertyBinding> bindings, String name) throws XMLStreamException {
-            CsdlNavigationPropertyBinding binding = new CsdlNavigationPropertyBinding();
-            binding.setPath(attr(element, "Path"));
-            binding.setTarget(attr(element, "Target"));
-            bindings.add(binding);
+              CsdlBindingTarget entitySet, String name) throws XMLStreamException {
+            if (name.equals("NavigationPropertyBinding")) {
+              CsdlNavigationPropertyBinding binding = new CsdlNavigationPropertyBinding();
+              binding.setPath(attr(element, "Path"));
+              binding.setTarget(attr(element, "Target"));
+              entitySet.getNavigationPropertyBindings().add(binding);
+            } else if (name.equals("Annotation")) {
+              readAnnotations(reader, element, entitySet);
+            }
           }
 
-        }.read(reader, element, bindings, "NavigationPropertyBinding");
+        }.read(reader, element, entitySet, "NavigationPropertyBinding", "Annotation");
       }
-    }.read(reader, element, schema, "EntitySet", "Singleton", "ActionImport", "FunctionImport");
+    }.read(reader, element, schema, "EntitySet", "Singleton", "ActionImport", "FunctionImport", "Annotation");
     schema.setEntityContainer(container);
   }
 
@@ -603,12 +939,14 @@ public class MetadataParser {
       void build(XMLEventReader reader, StartElement element, CsdlComplexType complexType, String name)
           throws XMLStreamException {
         if (name.equals("Property")) {
-          complexType.getProperties().add(readProperty(element));
+          complexType.getProperties().add(readProperty(reader, element));
         } else if (name.equals("NavigationProperty")) {
           complexType.getNavigationProperties().add(readNavigationProperty(reader, element));
+        } else if (name.equals("Annotation")) {
+          readAnnotations(reader, element, complexType);
         }
       }
-    }.read(reader, null, complexType, "Property", "NavigationProperty");
+    }.read(reader, null, complexType, "Property", "NavigationProperty", "Annotation");
   }
 
   abstract class ElementReader<T> {
@@ -617,7 +955,9 @@ public class MetadataParser {
       while (reader.hasNext()) {
         XMLEvent event = reader.peek();
 
-        event = skipAnnotations(reader, event);
+        if (!parseAnnotations) {
+          event = skipAnnotations(reader, event);
+        }
 
         if (!event.isStartElement() && !event.isEndElement()) {
           reader.nextEvent();
@@ -629,17 +969,19 @@ public class MetadataParser {
         for (String name : names) {
           if (event.isStartElement()) {
             element = event.asStartElement();
-            if (element.getName().getLocalPart().equals(name)) {
-              reader.nextEvent(); // advance cursor
+            if (element.getName().getLocalPart().equals(name)) {              
+              reader.nextEvent(); // advance cursor start which is current
               build(reader, element, t, name);
               hit = true;
+              break;
             }
           }
           if (event.isEndElement()) {
             EndElement e = event.asEndElement();
             if (e.getName().getLocalPart().equals(name)) {
-              reader.nextEvent(); // advance cursor
+              reader.nextEvent(); // advance cursor to end which is current
               hit = true;
+              break;
             }
           }
         }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/6d94f0e3/lib/server-core-ext/src/test/java/org/apache/olingo/server/core/MetadataParserAnnotationsTest.java
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/src/test/java/org/apache/olingo/server/core/MetadataParserAnnotationsTest.java b/lib/server-core-ext/src/test/java/org/apache/olingo/server/core/MetadataParserAnnotationsTest.java
new file mode 100644
index 0000000..7912dc8
--- /dev/null
+++ b/lib/server-core-ext/src/test/java/org/apache/olingo/server/core/MetadataParserAnnotationsTest.java
@@ -0,0 +1,208 @@
+/*
+ * 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.server.core;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.FileReader;
+import java.util.Arrays;
+
+import org.apache.olingo.commons.api.edm.FullQualifiedName;
+import org.apache.olingo.commons.api.edm.provider.CsdlAnnotation;
+import org.apache.olingo.commons.api.edm.provider.CsdlEdmProvider;
+import org.apache.olingo.commons.api.edm.provider.CsdlSchema;
+import org.apache.olingo.commons.api.edm.provider.CsdlTerm;
+import org.apache.olingo.commons.api.edm.provider.annotation.CsdlAnnotationPath;
+import org.apache.olingo.commons.api.edm.provider.annotation.CsdlApply;
+import org.apache.olingo.commons.api.edm.provider.annotation.CsdlCast;
+import org.apache.olingo.commons.api.edm.provider.annotation.CsdlCollection;
+import org.apache.olingo.commons.api.edm.provider.annotation.CsdlConstantExpression;
+import org.apache.olingo.commons.api.edm.provider.annotation.CsdlConstantExpression.ConstantExpressionType;
+import org.apache.olingo.commons.api.edm.provider.annotation.CsdlIf;
+import org.apache.olingo.commons.api.edm.provider.annotation.CsdlIsOf;
+import org.apache.olingo.commons.api.edm.provider.annotation.CsdlLabeledElement;
+import org.apache.olingo.commons.api.edm.provider.annotation.CsdlLabeledElementReference;
+import org.apache.olingo.commons.api.edm.provider.annotation.CsdlNavigationPropertyPath;
+import org.apache.olingo.commons.api.edm.provider.annotation.CsdlNull;
+import org.apache.olingo.commons.api.edm.provider.annotation.CsdlPath;
+import org.apache.olingo.commons.api.edm.provider.annotation.CsdlPropertyValue;
+import org.apache.olingo.commons.api.edm.provider.annotation.CsdlRecord;
+import org.apache.olingo.commons.api.edm.provider.annotation.CsdlUrlRef;
+import org.apache.olingo.commons.api.ex.ODataException;
+import org.junit.Before;
+import org.junit.Test;
+
+public class MetadataParserAnnotationsTest {
+  final String NS = "Org.OData.Core.V1";
+  final FullQualifiedName NSF = new FullQualifiedName(NS);
+
+  CsdlEdmProvider provider = null;
+
+  @Before
+  public void setUp() throws Exception {
+    MetadataParser parser = new MetadataParser();
+    parser.setParseAnnotations(true);
+    provider = (CsdlEdmProvider) parser.buildEdmProvider(new FileReader("src/test/resources/annotations.xml"));
+  }
+
+  CsdlAnnotation annotation(String term) throws ODataException {
+    CsdlSchema schema  = provider.getSchemas().get(0);
+    assertNotNull(schema.getAnnotations());
+    
+    return schema.getAnnotation(term);
+  }
+  
+  @Test
+  public void testConstantExpressionAttribute() throws ODataException {
+    CsdlAnnotation a = annotation("Core.Description");
+    assertNotNull(a);
+    assertTrue(a.getExpression() instanceof CsdlConstantExpression);
+    assertEquals("Core terms needed to write vocabularies", ((CsdlConstantExpression)a.getExpression()).getValue());
+    assertEquals(ConstantExpressionType.String, ((CsdlConstantExpression)a.getExpression()).getType());
+    
+    a = annotation("org.example.display.LastUpdated");
+    assertNotNull(a);
+    assertTrue(a.getExpression() instanceof CsdlConstantExpression);
+    assertEquals("2000-01-01T16:00:00.000-09:00", ((CsdlConstantExpression)a.getExpression()).getValue());
+    assertEquals(ConstantExpressionType.DateTimeOffset, ((CsdlConstantExpression)a.getExpression()).getType());
+  }
+
+  @Test
+  public void testCollection() throws ODataException {
+    CsdlAnnotation a = annotation("UI.CollectionFacet");
+    assertNotNull(a);
+    assertTrue(a.getExpression() instanceof CsdlCollection);
+    CsdlCollection exprs = ((CsdlCollection)a.getExpression());
+    assertEquals(2, exprs.getItems().size());
+    assertTrue(exprs.getItems().get(0) instanceof CsdlAnnotationPath);
+    CsdlAnnotationPath path = (CsdlAnnotationPath) exprs.getItems().get(0);
+    assertEquals("Supplier/@Communication.Contact", path.getValue());
+  }
+  
+  @Test
+  public void testApply() throws ODataException {
+    CsdlAnnotation a = annotation("org.example.display.DisplayNameApply");
+    assertNotNull(a);
+    assertTrue(a.getExpression() instanceof CsdlApply);
+    CsdlApply apply = ((CsdlApply)a.getExpression());
+
+    assertEquals("odata.concat", apply.getFunction());
+    assertEquals(7, apply.getParameters().size());
+    assertTrue(apply.getParameters().get(1) instanceof CsdlPath);
+    assertTrue(apply.getParameters().get(4) instanceof CsdlConstantExpression);
+  }  
+  
+  @Test
+  public void testCast() throws ODataException {
+    CsdlAnnotation a = annotation("org.example.display.Threshold");
+    assertNotNull(a);
+    assertTrue(a.getExpression() instanceof CsdlCast);
+    CsdlCast cast= (CsdlCast)a.getExpression();
+
+    assertEquals("Edm.Decimal", cast.getType());
+    assertTrue(cast.getValue() instanceof CsdlPath);
+    assertEquals("Average", ((CsdlPath)cast.getValue()).getValue());
+  }  
+  
+  @Test
+  public void testIf() throws ODataException {
+    CsdlAnnotation a = annotation("org.example.person.Gender");
+    assertNotNull(a);
+    assertTrue(a.getExpression() instanceof CsdlIf);
+    CsdlIf ifexpr = (CsdlIf)a.getExpression();
+
+    assertTrue(ifexpr.getGuard() instanceof CsdlPath);
+    assertTrue(ifexpr.getThen() instanceof CsdlConstantExpression);
+    assertTrue(ifexpr.getElse() instanceof CsdlConstantExpression);
+    
+    assertEquals("IsFemale", ((CsdlPath)ifexpr.getGuard()).getValue());
+    assertEquals("Female", ((CsdlConstantExpression)ifexpr.getThen()).getValue());
+    assertEquals("Male", ((CsdlConstantExpression)ifexpr.getElse()).getValue());
+  }  
+  
+  @Test
+  public void testIsOf() throws ODataException {
+    CsdlAnnotation a = annotation("Self.IsPreferredCustomer");
+    assertNotNull(a);
+    assertTrue(a.getExpression() instanceof CsdlIsOf);
+    CsdlIsOf isOf = (CsdlIsOf)a.getExpression();
+    assertEquals("Self.PreferredCustomer", isOf.getType());
+    assertTrue(isOf.getValue() instanceof CsdlPath);
+  }
+  
+  @Test
+  public void testLableledElement() throws ODataException {
+    CsdlAnnotation a = annotation("org.example.display.DisplayNameLabel");
+    assertNotNull(a);
+    assertTrue(a.getExpression() instanceof CsdlLabeledElement);
+    CsdlLabeledElement expr = (CsdlLabeledElement)a.getExpression();
+    assertEquals("CustomerFirstName", expr.getName());
+    assertTrue(expr.getValue() instanceof CsdlPath);
+  }
+  
+  @Test
+  public void testLableledReference() throws ODataException {
+    CsdlAnnotation a = annotation("org.example.display.DisplayNameLabelReference");
+    assertNotNull(a);
+    assertTrue(a.getExpression() instanceof CsdlLabeledElementReference);
+    CsdlLabeledElementReference expr = (CsdlLabeledElementReference)a.getExpression();
+    assertEquals("Model.CustomerFirstName", expr.getValue());
+  }
+  
+  @Test
+  public void testNull() throws ODataException {
+    CsdlAnnotation a = annotation("org.example.display.DisplayNameNull");
+    assertNotNull(a);
+    assertTrue(a.getExpression() instanceof CsdlNull);
+  }
+  
+  @Test
+  public void testRecord() throws ODataException {
+    CsdlAnnotation a = annotation("Capabilities.UpdateRestrictions");
+    assertNotNull(a);
+    assertTrue(a.getExpression() instanceof CsdlRecord);
+    CsdlRecord expr = (CsdlRecord)a.getExpression();
+    assertEquals(1, expr.getPropertyValues().size());
+    CsdlPropertyValue value = expr.getPropertyValues().get(0);
+    assertEquals("NonUpdatableNavigationProperties", value.getProperty());
+    assertTrue(value.getValue() instanceof CsdlCollection);
+    
+    CsdlCollection collection = (CsdlCollection)value.getValue(); 
+    assertEquals(2, collection.getItems().size());
+    assertEquals("Category", ((CsdlNavigationPropertyPath)collection.getItems().get(1)).getValue());
+  }
+  
+  @Test
+  public void testUrlRef() throws ODataException {
+    CsdlAnnotation a = annotation("Vocab.Supplier");
+    assertNotNull(a);
+    assertTrue(a.getExpression() instanceof CsdlUrlRef);
+    CsdlUrlRef expr = (CsdlUrlRef)a.getExpression();
+    assertTrue(expr.getValue() instanceof CsdlApply);
+    assertEquals(2, ((CsdlApply)expr.getValue()).getParameters().size());
+  }
+  
+  @Test
+  public void testTermAppliesTo() throws ODataException {
+    CsdlTerm term = this.provider.getTerm(new FullQualifiedName(NS, "IsURI"));
+    assertEquals(Arrays.asList("Property", "PropertyPath"), term.getAppliesTo());
+  }  
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/6d94f0e3/lib/server-core-ext/src/test/java/org/apache/olingo/server/core/MetadataParserTest.java
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/src/test/java/org/apache/olingo/server/core/MetadataParserTest.java b/lib/server-core-ext/src/test/java/org/apache/olingo/server/core/MetadataParserTest.java
index 5092357..97f19b5 100644
--- a/lib/server-core-ext/src/test/java/org/apache/olingo/server/core/MetadataParserTest.java
+++ b/lib/server-core-ext/src/test/java/org/apache/olingo/server/core/MetadataParserTest.java
@@ -54,7 +54,8 @@ public class MetadataParserTest {
   @Before
   public void setUp() throws Exception {
     MetadataParser parser = new MetadataParser();
-    provider = parser.buildEdmProvider(new FileReader("src/test/resources/trippin.xml"));
+    parser.setParseAnnotations(true);
+    provider = (CsdlEdmProvider) parser.buildEdmProvider(new FileReader("src/test/resources/trippin.xml"));
   }
 
   @Test

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/6d94f0e3/lib/server-core-ext/src/test/java/org/apache/olingo/server/core/ServiceDispatcherTest.java
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/src/test/java/org/apache/olingo/server/core/ServiceDispatcherTest.java b/lib/server-core-ext/src/test/java/org/apache/olingo/server/core/ServiceDispatcherTest.java
index a7fc922..90ead94 100644
--- a/lib/server-core-ext/src/test/java/org/apache/olingo/server/core/ServiceDispatcherTest.java
+++ b/lib/server-core-ext/src/test/java/org/apache/olingo/server/core/ServiceDispatcherTest.java
@@ -26,7 +26,6 @@ import java.io.File;
 import java.io.FileReader;
 import java.io.IOException;
 import java.net.URI;
-import java.util.Collections;
 
 import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
@@ -43,12 +42,10 @@ import org.apache.http.client.methods.HttpPost;
 import org.apache.http.client.methods.HttpPut;
 import org.apache.http.entity.StringEntity;
 import org.apache.http.impl.client.DefaultHttpClient;
-import org.apache.olingo.commons.api.edm.provider.CsdlEdmProvider;
 import org.apache.olingo.commons.api.http.HttpMethod;
 import org.apache.olingo.server.api.OData;
 import org.apache.olingo.server.api.ODataHttpHandler;
 import org.apache.olingo.server.api.ServiceMetadata;
-import org.apache.olingo.server.api.edmx.EdmxReference;
 import org.apache.olingo.server.core.requests.ActionRequest;
 import org.apache.olingo.server.core.requests.DataRequest;
 import org.apache.olingo.server.core.requests.FunctionRequest;
@@ -73,20 +70,19 @@ public class ServiceDispatcherTest {
   public class SampleODataServlet extends HttpServlet {
     private static final long serialVersionUID = 1L;
     private final ServiceHandler handler; // must be stateless
-    private final CsdlEdmProvider provider; // must be stateless
+    private final ServiceMetadata metadata; // must be stateless
 
-    public SampleODataServlet(ServiceHandler handler, CsdlEdmProvider provider) {
+    public SampleODataServlet(ServiceHandler handler, ServiceMetadata metadata) {
       this.handler = handler;
-      this.provider = provider;
+      this.metadata = metadata;
     }
 
     @Override
     public void service(HttpServletRequest request, HttpServletResponse response)
         throws IOException {
       OData odata = OData4Impl.newInstance();
-      ServiceMetadata metadata = odata.createServiceMetadata(this.provider, Collections.<EdmxReference> emptyList());
 
-      ODataHttpHandler handler = odata.createHandler(metadata);
+      ODataHttpHandler handler = odata.createHandler(this.metadata);
 
       handler.register(this.handler);
       handler.process(request, response);
@@ -95,14 +91,13 @@ public class ServiceDispatcherTest {
   
   public void beforeTest(ServiceHandler serviceHandler) throws Exception {
     MetadataParser parser = new MetadataParser();
-    CsdlEdmProvider edmProvider = parser.buildEdmProvider(new FileReader(
-        "src/test/resources/trippin.xml"));
+    ServiceMetadata metadata = parser.buildServiceMetadata(new FileReader("src/test/resources/trippin.xml"));
 
     File baseDir = new File(System.getProperty("java.io.tmpdir"));
     tomcat.setBaseDir(baseDir.getAbsolutePath());
     tomcat.getHost().setAppBase(baseDir.getAbsolutePath());
     Context cxt = tomcat.addContext("/trippin", baseDir.getAbsolutePath());
-    Tomcat.addServlet(cxt, "trippin", new SampleODataServlet(serviceHandler, edmProvider));
+    Tomcat.addServlet(cxt, "trippin", new SampleODataServlet(serviceHandler, metadata));
     cxt.addServletMapping("/*", "trippin");
     tomcat.setPort(TOMCAT_PORT);
     tomcat.start();

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/6d94f0e3/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinServlet.java
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinServlet.java b/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinServlet.java
index fbc74ef..036cd78 100644
--- a/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinServlet.java
+++ b/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinServlet.java
@@ -20,7 +20,6 @@ package org.apache.olingo.server.example;
 
 import java.io.FileReader;
 import java.io.IOException;
-import java.util.Collections;
 
 import javax.servlet.ServletConfig;
 import javax.servlet.ServletException;
@@ -29,11 +28,9 @@ import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import javax.xml.stream.XMLStreamException;
 
-import org.apache.olingo.commons.api.edm.provider.CsdlEdmProvider;
 import org.apache.olingo.server.api.OData;
 import org.apache.olingo.server.api.ODataHttpHandler;
 import org.apache.olingo.server.api.ServiceMetadata;
-import org.apache.olingo.server.api.edmx.EdmxReference;
 import org.apache.olingo.server.core.MetadataParser;
 import org.apache.olingo.server.core.OData4Impl;
 
@@ -50,16 +47,14 @@ public class TripPinServlet extends HttpServlet {
   public void service(HttpServletRequest request, HttpServletResponse response) throws IOException {
     OData odata = OData4Impl.newInstance();
     MetadataParser parser = new MetadataParser();
-    CsdlEdmProvider edmProvider = null;
+    ServiceMetadata metadata = null;
 
     try {
-      edmProvider = parser.buildEdmProvider(new FileReader("src/test/resources/trippin.xml"));
+      metadata = parser.buildServiceMetadata(new FileReader("src/test/resources/trippin.xml"));
     } catch (XMLStreamException e) {
       throw new IOException(e);
     }
 
-    ServiceMetadata metadata = odata.createServiceMetadata(edmProvider, Collections.<EdmxReference>emptyList());
-
     ODataHttpHandler handler = odata.createHandler(metadata);
 
     if (this.dataModel == null) {

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/6d94f0e3/lib/server-core-ext/src/test/resources/annotations.xml
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/src/test/resources/annotations.xml b/lib/server-core-ext/src/test/resources/annotations.xml
new file mode 100644
index 0000000..fce46a8
--- /dev/null
+++ b/lib/server-core-ext/src/test/resources/annotations.xml
@@ -0,0 +1,153 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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. -->
+<edmx:Edmx xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx"
+	Version="4.0">
+	<edmx:DataServices>
+		<Schema xmlns="http://docs.oasis-open.org/odata/ns/edm"
+			Namespace="Org.OData.Core.V1" Alias="Core">
+
+			<Annotation Term="Core.Description">
+				<String>Core terms needed to write vocabularies</String>
+			</Annotation>
+
+			<Annotation Term="org.example.display.Thumbnail">
+				<Binary>T0RhdGE</Binary>
+			</Annotation>
+
+			<Annotation Term="org.example.display.ReadOnly">
+				<Bool>true</Bool>
+			</Annotation>
+
+			<Annotation Term="org.example.display.LastUpdated"
+				DateTimeOffset="2000-01-01T16:00:00.000-09:00" />
+
+			<Annotation Term="UI.ReferenceFacet" AnnotationPath="Product/Supplier/@UI.LineItem" />
+
+			<Annotation Term="UI.CollectionFacet" Qualifier="Contacts">
+				<Collection>
+					<AnnotationPath>Supplier/@Communication.Contact</AnnotationPath>
+					<AnnotationPath>Customer/@Communication.Contact</AnnotationPath>
+				</Collection>
+			</Annotation>
+
+			<Annotation Term="org.example.display.DisplayNameApply">
+				<Apply Function="odata.concat">
+					<String>Product: </String>
+					<Path>ProductName</Path>
+					<String> (</String>
+					<Path>Available/Quantity</Path>
+					<String>
+					</String>
+					<Path>Available/Unit</Path>
+					<String> available)</String>
+				</Apply>
+			</Annotation>
+
+			<Annotation Term="org.example.display.Threshold">
+				<Cast Type="Edm.Decimal">
+					<Path>Average</Path>
+				</Cast>
+			</Annotation>
+			<Annotation Term="org.example.seo.SeoTerms">
+				<Collection>
+					<String>Product</String>
+					<String>Supplier</String>
+					<String>Customer</String>
+				</Collection>
+			</Annotation>
+
+			<Annotation Term="org.example.person.Gender">
+				<If>
+					<Path>IsFemale</Path>
+					<String>Female</String>
+					<String>Male</String>
+				</If>
+			</Annotation>
+
+			<Annotation Term="Self.IsPreferredCustomer">
+				<IsOf Type="Self.PreferredCustomer">
+					<Path>Customer</Path>
+				</IsOf>
+			</Annotation>
+
+			<Annotation Term="org.example.display.DisplayNameLabel">
+				<LabeledElement Name="CustomerFirstName">
+					<Path>FirstName</Path>
+				</LabeledElement>
+			</Annotation>
+
+			<Annotation Term="org.example.display.DisplayNameLabelReference">
+				<LabeledElementReference>Model.CustomerFirstName
+				</LabeledElementReference>
+			</Annotation>
+
+			<Annotation Term="org.example.display.DisplayNameNull">
+				<Null />
+			</Annotation>
+
+			<Annotation Term="Capabilities.UpdateRestrictions">
+				<Record>
+					<PropertyValue Property="NonUpdatableNavigationProperties">
+						<Collection>
+							<NavigationPropertyPath>Supplier</NavigationPropertyPath>
+							<NavigationPropertyPath>Category</NavigationPropertyPath>
+						</Collection>
+					</PropertyValue>
+				</Record>
+			</Annotation>
+
+			<Annotation Term="org.example.display.DisplayNamePath">
+				<Path>@vCard.Address#work/FullName</Path>
+			</Annotation>
+
+			<Term Name="IsURI" Type="Core.Tag" DefaultValue="true"
+				AppliesTo="Property PropertyPath">
+				<Annotation Term="Core.Description">
+					<String>
+						Properties and terms annotated with this term MUST contain a valid URI
+					</String>
+				</Annotation>
+				<Annotation Term="Core.RequiresType" String="Edm.String" />
+			</Term>
+			
+			<Annotation Term="org.example.person.Employee">
+				<Record>
+					<PropertyValue Property="GivenName" Path="FirstName" />
+					<PropertyValue Property="Surname" Path="LastName" />
+					<PropertyValue Property="Manager" Path="DirectSupervisor" />
+					<PropertyValue Property="CostCenter">
+						<UrlRef>
+							<Apply Function="odata.fillUriTemplate">
+								<String>http://host/anotherservice/CostCenters('{ccid}')
+								</String>
+								<LabeledElement Name="ccid" Path="CostCenterID" />
+							</Apply>
+						</UrlRef>
+					</PropertyValue>
+				</Record>
+			</Annotation>
+
+			<Annotation Term="Vocab.Supplier">
+				<UrlRef>
+					<Apply Function="odata.fillUriTemplate">
+						<String>http://host/service/Suppliers({suppID})</String>
+						<LabeledElement Name="suppID">
+							<Apply Function="odata.uriEncode">
+								<Path>SupplierId</Path>
+							</Apply>
+						</LabeledElement>
+					</Apply>
+				</UrlRef>
+			</Annotation>
+		</Schema>
+	</edmx:DataServices>
+</edmx:Edmx>
\ No newline at end of file


[10/22] olingo-odata4 git commit: [OLINGO-852] less warnings + general clean-up

Posted by mi...@apache.org.
[OLINGO-852] less warnings + general clean-up

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


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

Branch: refs/heads/OLINGO-832_StreamSerializerPoC
Commit: 5d7c1287f042fbb6c50e815c2dc1af9903b74951
Parents: 110c7b0
Author: Klaus Straubinger <kl...@sap.com>
Authored: Thu Feb 4 12:28:35 2016 +0100
Committer: Christian Amend <ch...@sap.com>
Committed: Thu Feb 4 12:42:29 2016 +0100

----------------------------------------------------------------------
 .../commons/AbstractInvocationHandler.java      |   17 +-
 .../AbstractStructuredInvocationHandler.java    |    2 +-
 .../commons/AnnotatationsInvocationHandler.java |    2 +-
 .../ComplexCollectionInvocationHandler.java     |    2 +-
 .../proxy/commons/ComplexInvocationHandler.java |    6 +-
 .../proxy/commons/EdmStreamValueHandler.java    |    2 +-
 .../EntityCollectionInvocationHandler.java      |    2 +-
 .../EntityContainerInvocationHandler.java       |    4 +-
 .../proxy/commons/EntityInvocationHandler.java  |    6 +-
 .../commons/EntitySetInvocationHandler.java     |    2 +-
 .../proxy/commons/InvokerInvocationHandler.java |    2 +-
 .../commons/OperationInvocationHandler.java     |    2 +-
 .../PrimitiveCollectionInvocationHandler.java   |    2 +-
 ...turedComposableInvokerInvocationHandler.java |    2 +-
 .../olingo/ext/proxy/utils/CoreUtils.java       |    5 +-
 .../org/apache/olingo/fit/AbstractServices.java | 1947 --------------
 .../main/java/org/apache/olingo/fit/Demo.java   |    6 +-
 .../java/org/apache/olingo/fit/OpenType.java    |    5 +-
 .../java/org/apache/olingo/fit/Services.java    | 2511 +++++++++++++++---
 .../org/apache/olingo/fit/Vocabularies.java     |   10 +-
 .../apache/olingo/fit/metadata/EntitySet.java   |    8 -
 .../olingo/fit/rest/OAuth2RequestFilter.java    |    3 +-
 .../fit/serializer/FITAtomDeserializer.java     |   13 +-
 .../olingo/fit/utils/AbstractUtilities.java     |   22 +-
 .../org/apache/olingo/fit/utils/Accept.java     |   31 +-
 .../org/apache/olingo/fit/utils/Commons.java    |   24 +-
 .../apache/olingo/fit/utils/ConstantKey.java    |   10 +-
 .../org/apache/olingo/fit/utils/Constants.java  |    7 -
 .../org/apache/olingo/fit/utils/FSManager.java  |   25 +-
 .../fit/utils/InjectableSerializerProvider.java |   42 -
 .../apache/olingo/fit/utils/JSONUtilities.java  |   14 +-
 .../olingo/fit/utils/MetadataLinkInfo.java      |  182 --
 .../apache/olingo/fit/utils/XMLUtilities.java   |    3 +
 .../proxy/demo/odatademo/types/Customer.java    |    6 +-
 .../proxy/demo/odatademo/types/Employee.java    |    6 +-
 .../demo/odatademo/types/FeaturedProduct.java   |    6 +-
 .../opentypesservice/types/IndexedRow.java      |    8 +-
 .../odatawcfservice/types/CreditCardPI.java     |    6 +-
 .../odatawcfservice/types/Customer.java         |    6 +-
 .../odatawcfservice/types/Employee.java         |    6 +-
 .../odatawcfservice/types/PublicCompany.java    |    8 +-
 .../tecsvc/client/EntityReferencesITCase.java   |   13 +-
 .../ExpandWithSystemQueryOptionsITCase.java     |   74 +-
 .../core/domain/AbstractClientEntitySet.java    |  114 -
 .../core/domain/ClientCollectionValueImpl.java  |    2 +-
 .../client/core/domain/ClientEntitySetImpl.java |   74 +-
 .../core/domain/ClientPrimitiveValueImpl.java   |    5 +-
 .../client/core/domain/ClientPropertyImpl.java  |  135 +-
 .../client/core/domain/ClientValuableImpl.java  |   22 +-
 .../core/serialization/ODataBinderImpl.java     |    2 +-
 .../apache/olingo/client/core/AbstractTest.java |    9 +-
 .../org/apache/olingo/client/core/AtomTest.java |    6 -
 .../olingo/client/core/EntitySetTest.java       |   22 +-
 .../apache/olingo/client/core/EntityTest.java   |   73 +-
 .../apache/olingo/client/core/ErrorTest.java    |    8 +-
 .../org/apache/olingo/client/core/JSONTest.java |   46 +-
 .../apache/olingo/client/core/MetadataTest.java |   33 +-
 .../olingo/client/core/PrimitiveValueTest.java  |   22 +-
 .../apache/olingo/client/core/PropertyTest.java |   38 +-
 .../olingo/client/core/ServiceDocumentTest.java |   16 +-
 .../client/core/uri/FilterFactoryTest.java      |    8 +-
 .../olingo/client/core/uri/URIBuilderTest.java  |   71 +-
 .../olingo/commons/api/edm/geo/Geospatial.java  |    7 +-
 .../core/edm/EdmNavigationPropertyImpl.java     |    3 +-
 .../commons/core/edm/EdmParameterImpl.java      |    3 +-
 .../commons/core/edm/EdmPropertyImpl.java       |    5 +-
 .../core/batchhandler/BatchFacadeImpl.java      |   18 +-
 .../server/core/batchhandler/BatchHandler.java  |    2 +-
 68 files changed, 2488 insertions(+), 3316 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AbstractInvocationHandler.java
----------------------------------------------------------------------
diff --git a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AbstractInvocationHandler.java b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AbstractInvocationHandler.java
index 258a496..ff4663e 100644
--- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AbstractInvocationHandler.java
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AbstractInvocationHandler.java
@@ -69,7 +69,7 @@ abstract class AbstractInvocationHandler implements InvocationHandler {
     return service.getContext();
   }
 
-  protected boolean isSelfMethod(final Method method, final Object[] args) {
+  protected boolean isSelfMethod(final Method method) {
     final Method[] selfMethods = getClass().getMethods();
 
     boolean result = false;
@@ -161,7 +161,7 @@ abstract class AbstractInvocationHandler implements InvocationHandler {
       CoreUtils.addProperties(getClient(), handler.getPropertyChanges(), template);
       final Object key = CoreUtils.getKey(getClient(), handler, handler.getUUID().getType(), template);
 
-      entityURI = CoreUtils.buildEditLink(getClient(), baseURI.toASCIIString(), template, key).build();
+      entityURI = CoreUtils.buildEditLink(getClient(), baseURI.toASCIIString(), key).build();
       template.setEditLink(entityURI);
     } else {
       entityURI = handler.getEntityURI();
@@ -182,32 +182,25 @@ abstract class AbstractInvocationHandler implements InvocationHandler {
     }
   }
 
-  protected static URIBuilder buildEntitySetURI(
-      final Class<?> ref,
-      final AbstractService<?> service) {
+  protected static URIBuilder buildEntitySetURI(final Class<?> ref, final AbstractService<?> service) {
 
-    final String containerNS;
     final String entitySetName;
     Annotation ann = ref.getAnnotation(EntitySet.class);
     if (ann instanceof EntitySet) {
-      containerNS = EntitySet.class.cast(ann).container();
       entitySetName = EntitySet.class.cast(ann).name();
     } else {
       ann = ref.getAnnotation(Singleton.class);
       if (ann instanceof Singleton) {
-        containerNS = Singleton.class.cast(ann).container();
         entitySetName = Singleton.class.cast(ann).name();
       } else {
-        containerNS = null;
         entitySetName = null;
       }
     }
 
-    return buildEntitySetURI(containerNS, entitySetName, service);
+    return buildEntitySetURI(entitySetName, service);
   }
 
-  protected static URIBuilder buildEntitySetURI(
-      final String containerNS, final String entitySetName, final AbstractService<?> service) {
+  protected static URIBuilder buildEntitySetURI(final String entitySetName, final AbstractService<?> service) {
 
     final URIBuilder uriBuilder = service.getClient().newURIBuilder();
     final StringBuilder entitySetSegment = new StringBuilder();

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AbstractStructuredInvocationHandler.java
----------------------------------------------------------------------
diff --git a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AbstractStructuredInvocationHandler.java b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AbstractStructuredInvocationHandler.java
index 96b3f26..a448186 100644
--- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AbstractStructuredInvocationHandler.java
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AbstractStructuredInvocationHandler.java
@@ -210,7 +210,7 @@ public abstract class AbstractStructuredInvocationHandler extends AbstractInvoca
             || "refs".equals(method.getName())) {
       invokeSelfMethod(method, args);
       return proxy;
-    } else if (isSelfMethod(method, args)) {
+    } else if (isSelfMethod(method)) {
       return invokeSelfMethod(method, args);
     } else if ("load".equals(method.getName()) && ArrayUtils.isEmpty(args)) {
       load();

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AnnotatationsInvocationHandler.java
----------------------------------------------------------------------
diff --git a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AnnotatationsInvocationHandler.java b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AnnotatationsInvocationHandler.java
index fcd5078..8f0951d 100644
--- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AnnotatationsInvocationHandler.java
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AnnotatationsInvocationHandler.java
@@ -55,7 +55,7 @@ public class AnnotatationsInvocationHandler extends AbstractInvocationHandler {
 
   @Override
   public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
-    if (isSelfMethod(method, args)) {
+    if (isSelfMethod(method)) {
       return invokeSelfMethod(method, args);
     } else if (method.getName().startsWith("get") && method.getName().endsWith("Annotations")) {
       final Method getter = proxy.getClass().getInterfaces()[0].getMethod(method.getName());

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/ComplexCollectionInvocationHandler.java
----------------------------------------------------------------------
diff --git a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/ComplexCollectionInvocationHandler.java b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/ComplexCollectionInvocationHandler.java
index ff4fc66..8699ed4 100644
--- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/ComplexCollectionInvocationHandler.java
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/ComplexCollectionInvocationHandler.java
@@ -80,7 +80,7 @@ public class ComplexCollectionInvocationHandler<T extends ComplexType<?>>
 
       invokeSelfMethod(method, args);
       return proxy;
-    } else if (isSelfMethod(method, args)) {
+    } else if (isSelfMethod(method)) {
       return invokeSelfMethod(method, args);
     } else if ("operations".equals(method.getName()) && ArrayUtils.isEmpty(args)) {
       final Class<?> returnType = method.getReturnType();

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/ComplexInvocationHandler.java
----------------------------------------------------------------------
diff --git a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/ComplexInvocationHandler.java b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/ComplexInvocationHandler.java
index 3aa3326..1e2197c 100644
--- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/ComplexInvocationHandler.java
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/ComplexInvocationHandler.java
@@ -63,11 +63,7 @@ public class ComplexInvocationHandler extends AbstractStructuredInvocationHandle
     return new ImmutablePair<ClientComplexValue, Class<?>>(complex, complexTypeRef);
   }
 
-  public static ComplexInvocationHandler getInstance(
-          final String propertyName,
-          final EntityInvocationHandler handler,
-          final Class<?> typeRef) {
-
+  public static ComplexInvocationHandler getInstance(final EntityInvocationHandler handler, final Class<?> typeRef) {
     final Pair<ClientComplexValue, Class<?>> init = init(typeRef, handler.service);
     return new ComplexInvocationHandler(init.getLeft(), init.getRight(), handler);
   }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EdmStreamValueHandler.java
----------------------------------------------------------------------
diff --git a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EdmStreamValueHandler.java b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EdmStreamValueHandler.java
index d197f58..c13a3cf 100644
--- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EdmStreamValueHandler.java
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EdmStreamValueHandler.java
@@ -59,7 +59,7 @@ public class EdmStreamValueHandler extends AbstractInvocationHandler {
       load();
       return proxy;
     } else {
-      if (isSelfMethod(method, args)) {
+      if (isSelfMethod(method)) {
         return invokeSelfMethod(method, args);
       } else {
         throw new NoSuchMethodException(method.getName());

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntityCollectionInvocationHandler.java
----------------------------------------------------------------------
diff --git a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntityCollectionInvocationHandler.java b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntityCollectionInvocationHandler.java
index 5c8da2c..e7d819a 100644
--- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntityCollectionInvocationHandler.java
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntityCollectionInvocationHandler.java
@@ -62,7 +62,7 @@ public class EntityCollectionInvocationHandler<T extends EntityType<?>>
             || "execute".equals(method.getName())) {
       invokeSelfMethod(method, args);
       return proxy;
-    } else if (isSelfMethod(method, args)) {
+    } else if (isSelfMethod(method)) {
       return invokeSelfMethod(method, args);
     } else if ("operations".equals(method.getName()) && ArrayUtils.isEmpty(args)) {
       final Class<?> returnType = method.getReturnType();

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntityContainerInvocationHandler.java
----------------------------------------------------------------------
diff --git a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntityContainerInvocationHandler.java b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntityContainerInvocationHandler.java
index cb72126..af8101b 100644
--- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntityContainerInvocationHandler.java
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntityContainerInvocationHandler.java
@@ -80,7 +80,7 @@ public final class EntityContainerInvocationHandler extends AbstractInvocationHa
 
   @Override
   public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
-    if (isSelfMethod(method, args)) {
+    if (isSelfMethod(method)) {
       return invokeSelfMethod(method, args);
     } else if ("flush".equals(method.getName()) && ArrayUtils.isEmpty(args)) {
       service.getPersistenceManager().flush();
@@ -114,7 +114,7 @@ public final class EntityContainerInvocationHandler extends AbstractInvocationHa
     final Class<?> typeRef = method.getReturnType();
     final Singleton singleton = method.getAnnotation(Singleton.class);
 
-    final URI uri = buildEntitySetURI(singleton.container(), singleton.name(), service).build();
+    final URI uri = buildEntitySetURI(singleton.name(), service).build();
     final EntityUUID uuid = new EntityUUID(uri, typeRef);
     LOG.debug("Ask for singleton '{}'", typeRef.getSimpleName());
 

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntityInvocationHandler.java
----------------------------------------------------------------------
diff --git a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntityInvocationHandler.java b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntityInvocationHandler.java
index c124402..e993140 100644
--- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntityInvocationHandler.java
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntityInvocationHandler.java
@@ -191,7 +191,7 @@ public class EntityInvocationHandler extends AbstractStructuredInvocationHandler
       this.uri = getClient().newURIBuilder(baseURI.toASCIIString());
     } else if (key != null) {
       final URIBuilder uriBuilder =
-          CoreUtils.buildEditLink(getClient(), entitySetURI.toASCIIString(), entity, key);
+          CoreUtils.buildEditLink(getClient(), entitySetURI.toASCIIString(), key);
 
       this.uri = uriBuilder;
       this.baseURI = this.uri.build();
@@ -219,7 +219,7 @@ public class EntityInvocationHandler extends AbstractStructuredInvocationHandler
     if (this.uri == null) {
       final URIBuilder uriBuilder =
           entity.getEditLink() == null
-              ? CoreUtils.buildEditLink(getClient(), getUUID().getEntitySetURI().toASCIIString(), entity, key)
+              ? CoreUtils.buildEditLink(getClient(), getUUID().getEntitySetURI().toASCIIString(), key)
               : getClient().newURIBuilder(entity.getEditLink().toASCIIString());
 
       this.uri = uriBuilder;
@@ -252,7 +252,7 @@ public class EntityInvocationHandler extends AbstractStructuredInvocationHandler
     if (this.uri == null) {
       final URIBuilder uriBuilder =
           getEntity().getEditLink() == null
-              ? CoreUtils.buildEditLink(getClient(), entitySetURI.toASCIIString(), getEntity(), key)
+              ? CoreUtils.buildEditLink(getClient(), entitySetURI.toASCIIString(), key)
               : getClient().newURIBuilder(getEntity().getEditLink().toASCIIString());
 
       this.uri = uriBuilder;

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntitySetInvocationHandler.java
----------------------------------------------------------------------
diff --git a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntitySetInvocationHandler.java b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntitySetInvocationHandler.java
index 8250f72..9d1970a 100644
--- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntitySetInvocationHandler.java
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntitySetInvocationHandler.java
@@ -84,7 +84,7 @@ public class EntitySetInvocationHandler<
 
       invokeSelfMethod(method, args);
       return proxy;
-    } else if (isSelfMethod(method, args)) {
+    } else if (isSelfMethod(method)) {
       return invokeSelfMethod(method, args);
     } else {
       throw new NoSuchMethodException(method.getName());

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/InvokerInvocationHandler.java
----------------------------------------------------------------------
diff --git a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/InvokerInvocationHandler.java b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/InvokerInvocationHandler.java
index 53208f7..3ed6121 100644
--- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/InvokerInvocationHandler.java
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/InvokerInvocationHandler.java
@@ -276,7 +276,7 @@ public class InvokerInvocationHandler<T, O extends Operations> extends AbstractI
       return Proxy.newProxyInstance(
               Thread.currentThread().getContextClassLoader(),
               new Class<?>[] {operationRef}, handler);
-    } else if (isSelfMethod(method, args)) {
+    } else if (isSelfMethod(method)) {
       return invokeSelfMethod(method, args);
     } else {
       throw new NoSuchMethodException(method.getName());

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/OperationInvocationHandler.java
----------------------------------------------------------------------
diff --git a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/OperationInvocationHandler.java b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/OperationInvocationHandler.java
index bdab06c..23cd25c 100644
--- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/OperationInvocationHandler.java
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/OperationInvocationHandler.java
@@ -133,7 +133,7 @@ final class OperationInvocationHandler extends AbstractInvocationHandler {
   @Override
   @SuppressWarnings({"unchecked", "rawtypes"})
   public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
-    if (isSelfMethod(method, args)) {
+    if (isSelfMethod(method)) {
       return invokeSelfMethod(method, args);
     } else {
       final Operation operation = method.getAnnotation(Operation.class);

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/PrimitiveCollectionInvocationHandler.java
----------------------------------------------------------------------
diff --git a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/PrimitiveCollectionInvocationHandler.java b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/PrimitiveCollectionInvocationHandler.java
index 553af6e..67d6e86 100644
--- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/PrimitiveCollectionInvocationHandler.java
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/PrimitiveCollectionInvocationHandler.java
@@ -75,7 +75,7 @@ public class PrimitiveCollectionInvocationHandler<T extends Serializable>
 
       invokeSelfMethod(method, args);
       return proxy;
-    } else if (isSelfMethod(method, args)) {
+    } else if (isSelfMethod(method)) {
       return invokeSelfMethod(method, args);
     } else if ("operations".equals(method.getName()) && ArrayUtils.isEmpty(args)) {
       final Class<?> returnType = method.getReturnType();

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/StructuredComposableInvokerInvocationHandler.java
----------------------------------------------------------------------
diff --git a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/StructuredComposableInvokerInvocationHandler.java b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/StructuredComposableInvokerInvocationHandler.java
index 41ec9ce..00670b3 100644
--- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/StructuredComposableInvokerInvocationHandler.java
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/StructuredComposableInvokerInvocationHandler.java
@@ -75,7 +75,7 @@ public class StructuredComposableInvokerInvocationHandler<T, O extends Operation
       return super.invoke(proxy, method, args);
     } else if ("operations".equals(method.getName()) && ArrayUtils.isEmpty(args)) {
       return super.invoke(proxy, method, args);
-    } else if (isSelfMethod(method, args)) {
+    } else if (isSelfMethod(method)) {
       return invokeSelfMethod(method, args);
     } else {
       throw new NoSuchMethodException(method.getName());

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/utils/CoreUtils.java
----------------------------------------------------------------------
diff --git a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/utils/CoreUtils.java b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/utils/CoreUtils.java
index 2776f3b..8f804fe 100644
--- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/utils/CoreUtils.java
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/utils/CoreUtils.java
@@ -378,7 +378,6 @@ public final class CoreUtils {
   public static URIBuilder buildEditLink(
       final EdmEnabledODataClient client,
       final String entitySetURI,
-      final ClientEntity entity,
       final Object key) {
 
     if (key == null) {
@@ -506,7 +505,7 @@ public final class CoreUtils {
               final Object complex = Proxy.newProxyInstance(
                   Thread.currentThread().getContextClassLoader(),
                   new Class<?>[] { getter.getReturnType() },
-                  ComplexInvocationHandler.getInstance(property.getName(), typeHandler, getter.getReturnType()));
+                  ComplexInvocationHandler.getInstance(typeHandler, getter.getReturnType()));
 
               populate(client, typeHandler, complex, Property.class, property.getValue().asComplex().iterator());
               setPropertyValue(bean, getter, complex);
@@ -530,7 +529,7 @@ public final class CoreUtils {
                   final Object collItem = Proxy.newProxyInstance(
                       Thread.currentThread().getContextClassLoader(),
                       new Class<?>[] { collItemClass },
-                      ComplexInvocationHandler.getInstance(property.getName(), typeHandler, collItemClass));
+                      ComplexInvocationHandler.getInstance(typeHandler, collItemClass));
 
                   populate(client, typeHandler, collItem, Property.class, value.asComplex().iterator());
                   collection.add(collItem);


[03/22] olingo-odata4 git commit: OLINGO-864: Refining the Edm.Date and Edm.Time behavior not to assume GMT

Posted by mi...@apache.org.
OLINGO-864: Refining the Edm.Date and Edm.Time behavior not to assume GMT


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

Branch: refs/heads/OLINGO-832_StreamSerializerPoC
Commit: f63bba70ad4c63a621b5a8e8186d50c172263989
Parents: b317b90 382ec16
Author: Ramesh Reddy <ra...@jboss.org>
Authored: Wed Feb 3 11:48:04 2016 -0600
Committer: Ramesh Reddy <ra...@jboss.org>
Committed: Wed Feb 3 11:48:04 2016 -0600

----------------------------------------------------------------------
 .../client/AbstractParamTecSvcITCase.java       | 14 ++++
 .../commons/core/edm/primitivetype/EdmDate.java |  5 +-
 .../edm/primitivetype/EdmDateTimeOffset.java    | 75 +++++++++++++-------
 .../core/edm/primitivetype/EdmTimeOfDay.java    | 20 ++----
 .../core/edm/primitivetype/EdmDateTest.java     |  1 -
 .../primitivetype/EdmDateTimeOffsetTest.java    |  9 ++-
 .../edm/primitivetype/EdmTimeOfDayTest.java     | 23 ++++--
 .../olingo/server/tecsvc/data/DataProvider.java |  6 ++
 .../server/tecsvc/data/DataProviderTest.java    | 14 ++++
 9 files changed, 115 insertions(+), 52 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/f63bba70/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/AbstractParamTecSvcITCase.java
----------------------------------------------------------------------
diff --cc fit/src/test/java/org/apache/olingo/fit/tecsvc/client/AbstractParamTecSvcITCase.java
index d6e35a3,0000000..a4d8a67
mode 100644,000000..100644
--- a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/AbstractParamTecSvcITCase.java
+++ b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/AbstractParamTecSvcITCase.java
@@@ -1,66 -1,0 +1,80 @@@
 +/*
 + * 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.hamcrest.CoreMatchers.startsWith;
 +import static org.junit.Assert.assertEquals;
 +import static org.junit.Assert.assertThat;
 +import static org.junit.Assert.assertTrue;
 +
 +import java.util.Arrays;
 +import java.util.List;
++import java.util.TimeZone;
 +
 +import org.apache.olingo.commons.api.format.ContentType;
++import org.apache.olingo.server.tecsvc.data.DataProvider;
++import org.junit.After;
++import org.junit.Before;
 +import org.junit.runner.RunWith;
 +import org.junit.runners.Parameterized;
 +
 +@RunWith(Parameterized.class)
 +public abstract class AbstractParamTecSvcITCase extends AbstractTecSvcITCase {
 +
 +  @Parameterized.Parameter
 +  public ContentType contentType;
 +
 +  /**
 +   * Returns a list of parameter arrays, in this case a list of one-element arrays
 +   * containing the content types to be used.
 +   */
 +  @Parameterized.Parameters(name = "{0}")
 +  public static List<ContentType[]> parameters() {
 +    return Arrays.asList(new ContentType[] { ContentType.APPLICATION_JSON },
 +        new ContentType[] { ContentType.APPLICATION_XML });
 +  }
 +
 +  @Override
 +  protected ContentType getContentType() {
 +    return contentType;
 +  }
 +
 +  protected void assertContentType(final String content) {
 +    assertThat(content, startsWith(contentType.toContentTypeString()));
 +  }
 +
 +  protected boolean isJson() {
 +    return ContentType.JSON.isCompatible(contentType);
 +  }
 +
 +  protected void assertShortOrInt(final int value, final Object n) {
 +    assertTrue(n instanceof Number);
 +    assertEquals(value, ((Number) n).intValue());
 +  }
++  
++  @Before
++  public void setup() {
++    DataProvider.setDefaultTimeZone("GMT");
++  }
++  
++  @After
++  public void teardown() {
++    DataProvider.setDefaultTimeZone(TimeZone.getDefault().getID());
++  }  
 +}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/f63bba70/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDate.java
----------------------------------------------------------------------
diff --cc lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDate.java
index 3eddca0,fb3f4ad..8588a5c
--- a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDate.java
+++ b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDate.java
@@@ -18,8 -18,9 +18,7 @@@
   */
  package org.apache.olingo.commons.core.edm.primitivetype;
  
 -import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
 -
  import java.util.Calendar;
- import java.util.TimeZone;
  import java.util.regex.Matcher;
  import java.util.regex.Pattern;
  

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/f63bba70/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDateTimeOffset.java
----------------------------------------------------------------------
diff --cc lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDateTimeOffset.java
index a7f57d1,95b0fa5..63c2c3c
--- a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDateTimeOffset.java
+++ b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDateTimeOffset.java
@@@ -18,16 -18,17 +18,17 @@@
   */
  package org.apache.olingo.commons.core.edm.primitivetype;
  
+ import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
+ 
  import java.sql.Time;
  import java.sql.Timestamp;
 -import java.text.DecimalFormat;
  import java.util.Calendar;
  import java.util.Date;
  import java.util.TimeZone;
  import java.util.regex.Matcher;
  import java.util.regex.Pattern;
  
- import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
 +
  /**
   * Implementation of the EDM primitive type DateTimeOffset.
   */
@@@ -60,8 -68,8 +61,9 @@@ public final class EdmDateTimeOffset ex
      }
  
      final String timeZoneOffset = matcher.group(9) == null || matcher.group(10) == null
 -            || matcher.group(10).matches("[-+]0+:0+") ? null : matcher.group(10);
 -    final Calendar dateTimeValue = Calendar.getInstance(TimeZone.getTimeZone("GMT" + timeZoneOffset));
 +        || matcher.group(10).matches("[-+]0+:0+") ? null : matcher.group(10);
-     final Calendar dateTimeValue = Calendar.getInstance(TimeZone.getTimeZone("GMT" + timeZoneOffset));
++    final TimeZone tz = TimeZone.getTimeZone("GMT" + ((timeZoneOffset == null) ? "" : timeZoneOffset));
++    final Calendar dateTimeValue = Calendar.getInstance(tz);
      if (dateTimeValue.get(Calendar.ZONE_OFFSET) == 0 && timeZoneOffset != null) {
        throw new EdmPrimitiveTypeException("The literal '" + value + "' has illegal content.");
      }
@@@ -150,19 -170,12 +165,12 @@@
  
    @Override
    protected <T> String internalValueToString(final T value,
 -          final Boolean isNullable, final Integer maxLength, final Integer precision,
 -          final Integer scale, final Boolean isUnicode) throws EdmPrimitiveTypeException {
 +      final Boolean isNullable, final Integer maxLength, final Integer precision,
 +      final Integer scale, final Boolean isUnicode) throws EdmPrimitiveTypeException {
  
-     Calendar dateTimeValue;
-     if (value instanceof Timestamp) {
-       final Calendar tmp = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
-       tmp.setTimeInMillis(((Timestamp) value).getTime());
-       dateTimeValue = createDateTime(tmp);
-     } else {
-       dateTimeValue = createDateTime(value);
-     }
- 
-     StringBuilder result = new StringBuilder();
+     final Calendar dateTimeValue = createDateTime(value, false);
+     
+     final StringBuilder result = new StringBuilder();
      final int year = dateTimeValue.get(Calendar.YEAR);
      appendTwoDigits(result, year / 100);
      appendTwoDigits(result, year % 100);
@@@ -269,4 -286,49 +283,17 @@@
        }
      }
    }
+ 
+   /**
 -   * Appends the given fractional seconds to the given string builder.
 -   *
 -   * @param result a {@link StringBuilder}
 -   * @param fractionalSeconds fractional seconds
 -   * @param precision the upper limit for decimal digits (optional, defaults to zero)
 -   * @throws IllegalArgumentException if precision is not met
 -   */
 -  protected static void appendFractionalSeconds(final StringBuilder result, final int fractionalSeconds,
 -          final Integer precision) throws IllegalArgumentException {
 -
 -    if (fractionalSeconds > 0) {
 -      String formatted = NANO_FORMAT.get().format(fractionalSeconds);
 -      int actualLength = formatted.length();
 -      boolean nonZeroFound = false;
 -      for (int i = formatted.length() - 1; i >= 0 && !nonZeroFound; i--) {
 -        if ('0' == formatted.charAt(i)) {
 -          actualLength--;
 -        } else {
 -          nonZeroFound = true;
 -        }
 -      }
 -
 -      if (precision == null || precision < actualLength) {
 -        throw new IllegalArgumentException();
 -      }
 -
 -      result.append('.').append(formatted.substring(0, actualLength));
 -    }
 -  }
 -  
 -  /**
+    * When the Timezone information is absent on the date time types, like EdmDate, EDMTimeOfDay, EdmDateTimeOffset
+    * this method defines the default timezone that should be used parse and output payload.
+    * User should set system property "defaultTimeZoneForEdmDateTypes" to control this. The default would be
+    * Java VM default if not defined.
+    *   
+    * @return Timezone
+    */
+   protected static TimeZone getDefaultTimeZone() {
+     String tz = System.getProperty("defaultTimeZoneForEdmDateTypes");
 -	return (tz != null)?TimeZone.getTimeZone(tz):TimeZone.getDefault();
 -  }
 -    
++	  return (tz != null)?TimeZone.getTimeZone(tz):TimeZone.getDefault();
++  }  
  }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/f63bba70/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmTimeOfDay.java
----------------------------------------------------------------------
diff --cc lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmTimeOfDay.java
index 7595e51,3090761..06ba239
--- a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmTimeOfDay.java
+++ b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmTimeOfDay.java
@@@ -18,9 -18,10 +18,8 @@@
   */
  package org.apache.olingo.commons.core.edm.primitivetype;
  
 -import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
 -
  import java.sql.Timestamp;
  import java.util.Calendar;
- import java.util.TimeZone;
  import java.util.regex.Matcher;
  import java.util.regex.Pattern;
  
@@@ -112,7 -101,13 +101,8 @@@ public final class EdmTimeOfDay extend
      EdmDateTimeOffset.appendTwoDigits(result, dateTimeValue.get(Calendar.SECOND));
  
      try {
-       EdmDateTimeOffset.appendFractionalSeconds(result, fractionalSecs, value instanceof Timestamp, precision);
 -      if (value instanceof Timestamp) {
 -    	int fractionalSecs = ((Timestamp) value).getNanos();
 -        EdmDateTimeOffset.appendFractionalSeconds(result, fractionalSecs, precision);
 -      } else {
 -        int fractionalSecs = dateTimeValue.get(Calendar.MILLISECOND);
 -        EdmDateTimeOffset.appendMilliseconds(result, fractionalSecs, precision);
 -      }
++      EdmDateTimeOffset.appendFractionalSeconds(result,
++          dateTimeValue.get(Calendar.MILLISECOND), value instanceof Timestamp, precision);
      } catch (final IllegalArgumentException e) {
        throw new EdmPrimitiveTypeException("The value '" + value + "' does not match the facets' constraints.", e);
      }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/f63bba70/lib/commons-core/src/test/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDateTest.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/f63bba70/lib/commons-core/src/test/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDateTimeOffsetTest.java
----------------------------------------------------------------------
diff --cc lib/commons-core/src/test/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDateTimeOffsetTest.java
index a352703,0b51925..5f2da25
--- a/lib/commons-core/src/test/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDateTimeOffsetTest.java
+++ b/lib/commons-core/src/test/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDateTimeOffsetTest.java
@@@ -18,10 -18,10 +18,9 @@@
   */
  package org.apache.olingo.commons.core.edm.primitivetype;
  
 -import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
 -import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
 -import org.junit.Test;
 +import static org.junit.Assert.assertEquals;
- import static org.junit.Assert.assertTrue;
  
 +import java.sql.Time;
  import java.sql.Timestamp;
  import java.util.Calendar;
  import java.util.Date;
@@@ -76,22 -74,12 +75,21 @@@ public class EdmDateTimeOffsetTest exte
      assertEquals("2012-02-29T23:32:03.007Z", instance.valueToString(millis, null, null, 3, null, null));
      assertEquals("1969-12-31T23:59:59.9Z", instance.valueToString(-100L, null, null, 1, null, null));
      assertEquals("1969-12-31T23:59:59.98Z", instance.valueToString(-20L, null, null, 2, null, null));
 -
 +    
 +    assertEquals("2012-02-29T23:32:03.007Z", instance.valueToString(new Time(millis), null, null, 3, null, null));
 +    assertEquals("1969-12-31T23:59:59.9Z", instance.valueToString(new Time(-100L), null, null, 1, null, null));
 +    assertEquals("1969-12-31T23:59:59.98Z", instance.valueToString(new Time(-20L), null, null, 2, null, null));
 +    
      final Date date = new Date(millis);
-     final String time = date.toString().substring(11, 19);
-     assertTrue(instance.valueToString(date, null, null, 3, null, null).contains(time));
+     assertEquals("2012-02-29T23:32:03.007Z", instance.valueToString(date, null, null, 3, null, null));
  
 +    Timestamp timestamp = new Timestamp(0);
 +    timestamp.setNanos(120);
 +    assertEquals("1970-01-01T00:00:00.00000012Z", instance.valueToString(timestamp, null, null, 8, null, null));
 +
      expectFacetsErrorInValueToString(instance, millis, null, null, null, null, null);
      expectFacetsErrorInValueToString(instance, 3L, null, null, 2, null, null);
 +    expectFacetsErrorInValueToString(instance, timestamp, null, null, 7, null, null);
  
      expectTypeErrorInValueToString(instance, 0);
    }
@@@ -133,14 -121,7 +131,15 @@@
          Long.class));
      assertEquals(Long.valueOf(120L), instance.valueOfString("1970-01-01T00:00:00.12", null, null, 2, null, null,
          Long.class));
 -
 +    
 +    assertEquals(new Time(120000L), instance.valueOfString("1970-01-01T00:02", null, null, null, null, null,
 +        Time.class));
-     assertEquals(new Time(12L), instance.valueOfString("1970-01-01T00:00:00.012", null, null, 3, null, null,
++    // 0L because java.sql.Time does not keep track of fraction of milliseconds
++    assertEquals(new Time(0L), instance.valueOfString("1970-01-01T00:00:00.012", null, null, 3, null, null,
 +        Time.class));
-     assertEquals(new Time(120L), instance.valueOfString("1970-01-01T00:00:00.12", null, null, 2, null, null,
++    assertEquals(new Time(0L), instance.valueOfString("1970-01-01T00:00:00.12", null, null, 2, null, null,
 +        Time.class));
 +    
      expectFacetsErrorInValueOfString(instance, "2012-02-29T23:32:02.9Z", null, null, null, null, null);
      expectFacetsErrorInValueOfString(instance, "2012-02-29T23:32:02.9Z", null, null, 0, null, null);
      expectContentErrorInValueOfString(instance, "2012-02-29T23:32:02X");

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/f63bba70/lib/commons-core/src/test/java/org/apache/olingo/commons/core/edm/primitivetype/EdmTimeOfDayTest.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/f63bba70/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataProvider.java
----------------------------------------------------------------------
diff --cc lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataProvider.java
index 20cbf94,878efce..5190c71
--- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataProvider.java
+++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataProvider.java
@@@ -512,151 -473,55 +512,157 @@@ public class DataProvider 
      entity.getProperties().remove(entity.getProperty(MEDIA_PROPERTY_NAME));
      entity.addProperty(DataCreator.createPrimitive(MEDIA_PROPERTY_NAME, media));
      entity.setMediaContentType(type);
 +    entity.setMediaETag("W/\"" + UUID.randomUUID() + "\"");
 +  }
 +
 +  public EntityCollection readFunctionEntityCollection(final EdmFunction function, final List<UriParameter> parameters,
 +      final UriInfoResource uriInfo) throws DataProviderException {
 +    return FunctionData.entityCollectionFunction(function.getName(),
 +        getFunctionParameters(function, parameters, uriInfo),
 +        data);
 +  }
 +
 +  public Entity readFunctionEntity(final EdmFunction function, final List<UriParameter> parameters,
 +      final UriInfoResource uriInfo) throws DataProviderException {
 +    return FunctionData.entityFunction(function.getName(),
 +        getFunctionParameters(function, parameters, uriInfo),
 +        data);
 +  }
 +
 +  public Property readFunctionPrimitiveComplex(final EdmFunction function, final List<UriParameter> parameters,
 +      final UriInfoResource uriInfo) throws DataProviderException {
 +    return FunctionData.primitiveComplexFunction(function.getName(),
 +        getFunctionParameters(function, parameters, uriInfo),
 +        data);
 +  }
 +
 +  private Map<String, Parameter> getFunctionParameters(final EdmFunction function,
 +      final List<UriParameter> parameters, final UriInfoResource uriInfo) throws DataProviderException {
 +    Map<String, Parameter> values = new HashMap<String, Parameter>();
 +    for (final UriParameter parameter : parameters) {
 +      final EdmParameter edmParameter = function.getParameter(parameter.getName());
 +      final String text = parameter.getAlias() == null ?
 +          parameter.getText() :
 +          uriInfo.getValueForAlias(parameter.getAlias());
 +      if (text != null) {
 +        try {
 +          values.put(parameter.getName(),
 +              odata.createFixedFormatDeserializer().parameter(text, edmParameter));
 +        } catch (final DeserializerException e) {
 +          throw new DataProviderException("Invalid function parameter.", HttpStatusCode.BAD_REQUEST, e);
 +        }
 +      }
 +    }
 +    return values;
    }
  
 -  public EntityCollection readFunctionEntitySet(final EdmFunction function, final List<UriParameter> parameters)
 +  public Property processActionPrimitive(final String name, final Map<String, Parameter> actionParameters)
        throws DataProviderException {
 -    return FunctionData.entityCollectionFunction(function.getName(), parameters, data);
 +    return ActionData.primitiveAction(name, actionParameters);
    }
  
 -  public Entity readFunctionEntity(final EdmFunction function, final List<UriParameter> parameters)
 +  public Property processActionComplex(final String name, final Map<String, Parameter> actionParameters)
        throws DataProviderException {
 -    return FunctionData.entityFunction(function.getName(), parameters, data);
 +    return ActionData.complexAction(name, actionParameters);
    }
  
 -  public Property readFunctionPrimitiveComplex(final EdmFunction function, final List<UriParameter> parameters)
 +  public Property processActionComplexCollection(final String name, final Map<String, Parameter> actionParameters)
        throws DataProviderException {
 -    return FunctionData.primitiveComplexFunction(function.getName(), parameters, data);
 +    return ActionData.complexCollectionAction(name, actionParameters);
    }
  
 -  public Property processActionPrimitive(String name, Map<String, Parameter> actionParameters)
 +  public Property processActionPrimitiveCollection(final String name, final Map<String, Parameter> actionParameters)
        throws DataProviderException {
 -    return ActionData.primitiveAction(name, actionParameters);
 +    return ActionData.primitiveCollectionAction(name, actionParameters, odata);
    }
  
 -  public Property processActionPrimitiveCollection(String name, Map<String, Parameter> actionParameters)
 +  public EntityActionResult processActionEntity(final String name, final Map<String, Parameter> actionParameters)
        throws DataProviderException {
 -    return ActionData.primitiveCollectionAction(name, actionParameters);
 +    return ActionData.entityAction(name, actionParameters, data, odata, edm);
    }
  
 -  public void setEdm(final Edm edm) {
 -    this.edm = edm;
 +  public EntityCollection processActionEntityCollection(final String name,
 +      final Map<String, Parameter> actionParameters) throws DataProviderException {
 +    return ActionData.entityCollectionAction(name, actionParameters, odata, edm);
    }
  
 -  public void setOData(final OData odata) {
 -    this.odata = odata;
 +  public void createReference(final Entity entity, final EdmNavigationProperty navigationProperty, final URI entityId,
 +      final String rawServiceRoot) throws DataProviderException {
 +    setLink(navigationProperty, entity, getEntityByReference(entityId.toASCIIString(), rawServiceRoot));
    }
  
 -  public static class DataProviderException extends ODataApplicationException {
 -    private static final long serialVersionUID = 5098059649321796156L;
 +  public void deleteReference(final Entity entity, final EdmNavigationProperty navigationProperty,
 +      final String entityId, final String rawServiceRoot) throws DataProviderException {
  
 -    public DataProviderException(final String message, final Throwable throwable) {
 -      super(message, HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode(), Locale.ROOT, throwable);
 +    if (navigationProperty.isCollection()) {
 +      final Entity targetEntity = getEntityByReference(entityId, rawServiceRoot);
 +      final Link navigationLink = entity.getNavigationLink(navigationProperty.getName());
 +
 +      if (navigationLink != null && navigationLink.getInlineEntitySet() != null
 +          && navigationLink.getInlineEntitySet().getEntities().contains(targetEntity)) {
 +
 +        // Remove partner single-valued navigation property
 +        if (navigationProperty.getPartner() != null) {
 +          final EdmNavigationProperty edmPartnerNavigationProperty = navigationProperty.getPartner();
 +          if (!edmPartnerNavigationProperty.isCollection() && !edmPartnerNavigationProperty.isNullable()) {
 +            throw new DataProviderException("Navigation property must not be null", HttpStatusCode.BAD_REQUEST);
 +          } else if (!edmPartnerNavigationProperty.isCollection()) {
 +            removeLink(edmPartnerNavigationProperty, targetEntity);
 +          } else if (edmPartnerNavigationProperty.isCollection()
 +              && edmPartnerNavigationProperty.getPartner() != null) {
 +            // Bidirectional referential constraint
 +            final Link partnerNavigationLink = targetEntity.getNavigationLink(edmPartnerNavigationProperty.getName());
 +            if (partnerNavigationLink != null && partnerNavigationLink.getInlineEntitySet() != null) {
 +              partnerNavigationLink.getInlineEntitySet().getEntities().remove(entity);
 +            }
 +          }
 +        }
 +
 +        // Remove target entity from collection-valued navigation property
 +        navigationLink.getInlineEntitySet().getEntities().remove(targetEntity);
 +      } else {
 +        throw new DataProviderException("Entity not found", HttpStatusCode.NOT_FOUND);
 +      }
 +    } else {
 +      if (navigationProperty.isNullable()) {
 +        removeLink(navigationProperty, entity);
 +      } else {
 +        throw new DataProviderException("Navigation property must not be null", HttpStatusCode.BAD_REQUEST);
 +      }
      }
 +  }
  
 -    public DataProviderException(final String message) {
 -      super(message, HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode(), Locale.ROOT);
 +  protected Entity getEntityByReference(final String entityId, final String rawServiceRoot)
 +      throws DataProviderException {
 +    try {
 +      final UriResourceEntitySet uriResource = odata.createUriHelper().parseEntityId(edm, entityId, rawServiceRoot);
 +      final Entity targetEntity = read(uriResource.getEntitySet(), uriResource.getKeyPredicates());
 +
 +      if (targetEntity != null) {
 +        return targetEntity;
 +      } else {
 +        throw new DataProviderException("Entity not found", HttpStatusCode.NOT_FOUND);
 +      }
 +    } catch (DeserializerException e) {
 +      throw new DataProviderException("Invalid entity-id", HttpStatusCode.BAD_REQUEST, e);
      }
 +  }
  
 -    public DataProviderException(final String message, HttpStatusCode statusCode) {
 +  public static class DataProviderException extends ODataApplicationException {
 +    private static final long serialVersionUID = 5098059649321796156L;
 +
 +    public DataProviderException(final String message, final HttpStatusCode statusCode) {
        super(message, statusCode.getStatusCode(), Locale.ROOT);
      }
 +
 +    public DataProviderException(final String message, final HttpStatusCode statusCode, final Throwable throwable) {
 +      super(message, statusCode.getStatusCode(), Locale.ROOT, throwable);
 +    }
    }
+ 
++  //CHECKSTYLE:OFF
++  public static void setDefaultTimeZone(String tz) {
++    System.setProperty("defaultTimeZoneForEdmDateTypes", tz);
++  }
++  //CHECKSTYLE:ON
  }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/f63bba70/lib/server-tecsvc/src/test/java/org/apache/olingo/server/tecsvc/data/DataProviderTest.java
----------------------------------------------------------------------
diff --cc lib/server-tecsvc/src/test/java/org/apache/olingo/server/tecsvc/data/DataProviderTest.java
index 6bd6463,c9a8e65..b2bf587
--- a/lib/server-tecsvc/src/test/java/org/apache/olingo/server/tecsvc/data/DataProviderTest.java
+++ b/lib/server-tecsvc/src/test/java/org/apache/olingo/server/tecsvc/data/DataProviderTest.java
@@@ -21,6 -21,6 +21,7 @@@ package org.apache.olingo.server.tecsvc
  import java.util.Arrays;
  import java.util.Collections;
  import java.util.List;
++import java.util.TimeZone;
  
  import org.apache.olingo.commons.api.data.ComplexValue;
  import org.apache.olingo.commons.api.data.Entity;
@@@ -33,7 -34,7 +34,9 @@@ import org.apache.olingo.server.api.ODa
  import org.apache.olingo.server.api.edmx.EdmxReference;
  import org.apache.olingo.server.api.uri.UriParameter;
  import org.apache.olingo.server.tecsvc.provider.EdmTechProvider;
++import org.junit.After;
  import org.junit.Assert;
++import org.junit.Before;
  import org.junit.Test;
  import org.mockito.Mockito;
  
@@@ -52,9 -53,9 +55,19 @@@ public class DataProviderTest 
    private final EdmEntitySet esMixPrimCollComp = entityContainer.getEntitySet("ESMixPrimCollComp");
    private final EdmEntitySet esMedia = entityContainer.getEntitySet("ESMedia");
  
++  @Before
++  public void setup() {
++    DataProvider.setDefaultTimeZone("GMT");
++  }
++  
++  @After
++  public void teardown() {
++    DataProvider.setDefaultTimeZone(TimeZone.getDefault().getID());
++  }
++  
    @Test
    public void esAllPrimEntity() throws Exception {
 -    final DataProvider dataProvider = new DataProvider();
 +    final DataProvider dataProvider = new DataProvider(oData, edm);
      final Entity entity = dataProvider.readAll(esAllPrim).getEntities().get(2);
      Assert.assertEquals(16, entity.getProperties().size());
  
@@@ -82,6 -83,6 +95,7 @@@
          mockParameter("PropertySByte", "127"),
          mockParameter("PropertyString", "'First'"),
          mockParameter("PropertyTimeOfDay", "02:48:21"))));
++    
    }
  
    @Test


[18/22] olingo-odata4 git commit: OLINGO-861: Adding support to resolve entities defined in the reference documents

Posted by mi...@apache.org.
OLINGO-861: Adding support to resolve entities defined in the reference documents


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

Branch: refs/heads/OLINGO-832_StreamSerializerPoC
Commit: 801899a0859bb2aa6bad567d7cff243b0c25a58d
Parents: 7a68ae6
Author: Ramesh Reddy <ra...@jboss.org>
Authored: Wed Feb 10 10:03:20 2016 -0600
Committer: Ramesh Reddy <ra...@jboss.org>
Committed: Wed Feb 10 10:03:20 2016 -0600

----------------------------------------------------------------------
 .../olingo/server/core/MetadataParser.java      |  66 ++++++++++--
 .../olingo/server/core/ReferenceResolver.java   |  32 ++++++
 .../server/core/SchemaBasedEdmProvider.java     | 104 ++++++++++++++++---
 3 files changed, 180 insertions(+), 22 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/801899a0/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/MetadataParser.java
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/MetadataParser.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/MetadataParser.java
index e8122d7..b564792 100644
--- a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/MetadataParser.java
+++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/MetadataParser.java
@@ -18,9 +18,12 @@
  */
 package org.apache.olingo.server.core;
 
+import java.io.IOException;
 import java.io.Reader;
+import java.net.MalformedURLException;
 import java.net.URI;
 import java.net.URISyntaxException;
+import java.net.URL;
 import java.util.ArrayList;
 import java.util.Arrays;
 
@@ -33,6 +36,7 @@ import javax.xml.stream.events.EndElement;
 import javax.xml.stream.events.StartElement;
 import javax.xml.stream.events.XMLEvent;
 
+import org.apache.olingo.commons.api.edm.EdmException;
 import org.apache.olingo.commons.api.edm.FullQualifiedName;
 import org.apache.olingo.commons.api.edm.geo.SRID;
 import org.apache.olingo.commons.api.edm.provider.CsdlAction;
@@ -42,7 +46,6 @@ import org.apache.olingo.commons.api.edm.provider.CsdlAnnotation;
 import org.apache.olingo.commons.api.edm.provider.CsdlAnnotations;
 import org.apache.olingo.commons.api.edm.provider.CsdlBindingTarget;
 import org.apache.olingo.commons.api.edm.provider.CsdlComplexType;
-import org.apache.olingo.commons.api.edm.provider.CsdlEdmProvider;
 import org.apache.olingo.commons.api.edm.provider.CsdlEntityContainer;
 import org.apache.olingo.commons.api.edm.provider.CsdlEntitySet;
 import org.apache.olingo.commons.api.edm.provider.CsdlEntityType;
@@ -92,16 +95,22 @@ import org.apache.olingo.server.api.edmx.EdmxReferenceIncludeAnnotation;
  */
 public class MetadataParser {
   private boolean parseAnnotations = false;
-
+  private final String XML_LINK_NS = "http://www.w3.org/1999/xlink";
+  private ReferenceResolver referenceResolver = new DefaultReferenceResolver();
+  
   public void setParseAnnotations(boolean f) {
     this.parseAnnotations = true;
   }
   
+  public void setReferenceResolver(ReferenceResolver resolver) {
+    this.referenceResolver = resolver;
+  }
+  
   public ServiceMetadata buildServiceMetadata(Reader csdl) throws XMLStreamException {
     XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
     XMLEventReader reader = xmlInputFactory.createXMLEventReader(csdl);
 
-    SchemaBasedEdmProvider provider = new SchemaBasedEdmProvider();
+    SchemaBasedEdmProvider provider = new SchemaBasedEdmProvider(referenceResolver);
     final ArrayList<EdmxReference> references = new ArrayList<EdmxReference>();
     
     new ElementReader<SchemaBasedEdmProvider>() {
@@ -109,6 +118,8 @@ public class MetadataParser {
       void build(XMLEventReader reader, StartElement element, SchemaBasedEdmProvider provider,
           String name) throws XMLStreamException {
         String version = attr(element, "Version");
+        String xmlBase = attrNS(element, XML_LINK_NS, "base");
+        provider.setXMLBase(xmlBase);
         if ("4.0".equals(version)) {
           readDataServicesAndReference(reader, element, provider, references);
         } else {
@@ -124,14 +135,18 @@ public class MetadataParser {
                   event.asStartElement().getName().getLocalPart() : 
                   event.asEndElement().getName().getLocalPart()));
     }
+    provider.addReferences(references);
     return new ServiceMetadataImpl(provider, references, null);
   }
 
-  CsdlEdmProvider buildEdmProvider(Reader csdl) throws XMLStreamException {
+  SchemaBasedEdmProvider buildEdmProvider(Reader csdl) throws XMLStreamException {
     XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
     XMLEventReader reader = xmlInputFactory.createXMLEventReader(csdl);
-
-    SchemaBasedEdmProvider provider = new SchemaBasedEdmProvider();
+    return buildEdmProvider(reader);
+  } 
+  
+  SchemaBasedEdmProvider buildEdmProvider(XMLEventReader reader) throws XMLStreamException {
+    SchemaBasedEdmProvider provider = new SchemaBasedEdmProvider(this.referenceResolver);
     new ElementReader<SchemaBasedEdmProvider>() {
       @Override
       void build(XMLEventReader reader, StartElement element, SchemaBasedEdmProvider provider,
@@ -141,8 +156,7 @@ public class MetadataParser {
           readDataServicesAndReference(reader, element, provider, new ArrayList<EdmxReference>());
         }
       }
-    }.read(reader, null, provider, "Edmx");
-
+    }.read(reader, null, provider, "Edmx");    
     return provider;
   }  
   
@@ -776,6 +790,14 @@ public class MetadataParser {
     return null;
   }
 
+  private String attrNS(StartElement element, String ns, String name) {
+    Attribute attr = element.getAttributeByName(new QName(ns, name));
+    if (attr != null) {
+      return attr.getValue();
+    }
+    return null;
+  }  
+  
   private CsdlProperty readProperty(XMLEventReader reader, StartElement element)
       throws XMLStreamException {
     CsdlProperty property = new CsdlProperty();
@@ -1020,4 +1042,32 @@ public class MetadataParser {
     abstract void build(XMLEventReader reader, StartElement element, T t, String name)
         throws XMLStreamException;
   }
+  
+  class DefaultReferenceResolver implements ReferenceResolver{
+    @Override
+    public SchemaBasedEdmProvider resolveReference(URI referenceUri, String xmlBase) {
+      URL schemaURL = null;
+      try {
+        if (referenceUri.isAbsolute()) {
+          schemaURL = referenceUri.toURL();
+        } else {
+          if (xmlBase != null) {
+            schemaURL = new URL(xmlBase+referenceUri.toString());
+          } else {
+            throw new EdmException("No xml:base set to read the references from the metadata");
+          }        
+        }
+        
+        XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
+        XMLEventReader reader = xmlInputFactory.createXMLEventReader(schemaURL.openStream());
+        return buildEdmProvider(reader);
+      } catch (MalformedURLException e) {
+        throw new EdmException(e);
+      } catch (XMLStreamException e) {
+        throw new EdmException(e);
+      } catch (IOException e) {
+        throw new EdmException(e);
+      }
+    }
+  }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/801899a0/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ReferenceResolver.java
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ReferenceResolver.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ReferenceResolver.java
new file mode 100644
index 0000000..f7d5101
--- /dev/null
+++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ReferenceResolver.java
@@ -0,0 +1,32 @@
+/*
+ * 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.server.core;
+
+import java.net.URI;
+
+public interface ReferenceResolver {
+  /**
+   * Resolve the reference locally or from redirection from different source than defined in the
+   * metadata document.  
+   * @param referenceUri reference URI for the schema file 
+   * @param xmlBase xml:base if provided by the metadata document; null otherwise
+   * @return
+   */
+  SchemaBasedEdmProvider resolveReference(URI referenceUri, String xmlBase);
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/801899a0/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/SchemaBasedEdmProvider.java
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/SchemaBasedEdmProvider.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/SchemaBasedEdmProvider.java
index 0612302..a2f23f6 100644
--- a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/SchemaBasedEdmProvider.java
+++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/SchemaBasedEdmProvider.java
@@ -19,8 +19,9 @@
 package org.apache.olingo.server.core;
 
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
 
 import org.apache.olingo.commons.api.edm.FullQualifiedName;
 import org.apache.olingo.commons.api.edm.provider.CsdlAction;
@@ -41,11 +42,22 @@ import org.apache.olingo.commons.api.edm.provider.CsdlSingleton;
 import org.apache.olingo.commons.api.edm.provider.CsdlTerm;
 import org.apache.olingo.commons.api.edm.provider.CsdlTypeDefinition;
 import org.apache.olingo.commons.api.ex.ODataException;
+import org.apache.olingo.server.api.edmx.EdmxReference;
+import org.apache.olingo.server.api.edmx.EdmxReferenceInclude;
 
 public class SchemaBasedEdmProvider implements CsdlEdmProvider {
   private final List<CsdlSchema> edmSchemas = new ArrayList<CsdlSchema>();
+  private final Map<String, EdmxReference> references = new ConcurrentHashMap<String, EdmxReference>();
+  private final Map<String, SchemaBasedEdmProvider> referenceSchemas 
+    = new ConcurrentHashMap<String, SchemaBasedEdmProvider>();
+  private String xmlBase;
+  private ReferenceResolver referenceResolver;
+  
+  public SchemaBasedEdmProvider(ReferenceResolver referenceResolver) {
+    this.referenceResolver = referenceResolver;
+  }
 
-  public void addSchema(CsdlSchema schema) {
+  void addSchema(CsdlSchema schema) {
     this.edmSchemas.add(schema);
   }
 
@@ -55,6 +67,39 @@ public class SchemaBasedEdmProvider implements CsdlEdmProvider {
         return s;
       }
     }
+    return getReferenceSchema(ns);
+  }
+
+  private CsdlSchema getReferenceSchema(String ns) {
+    if (ns == null) {
+      return null;
+    }
+    if (this.referenceSchemas.get(ns) == null) {
+      EdmxReference reference = this.references.get(ns);
+      if (reference != null) {
+        SchemaBasedEdmProvider provider = this.referenceResolver.resolveReference(reference.getUri(), xmlBase);
+        for (EdmxReferenceInclude include : reference.getIncludes()) {
+          this.referenceSchemas.put(include.getNamespace(), provider);
+          if (include.getAlias() != null) {
+            CsdlSchema schema = provider.getSchema(include.getNamespace());
+            schema.setAlias(include.getAlias());
+            this.referenceSchemas.put(include.getAlias(), provider);
+          }
+        }
+      }
+    }
+    
+    if (this.referenceSchemas.get(ns) != null) {
+      return this.referenceSchemas.get(ns).getSchema(ns);  
+    }
+    
+    // it is possible that we may be looking for Reference schema of Reference
+    for (SchemaBasedEdmProvider provider:this.referenceSchemas.values()) {
+      CsdlSchema schema = provider.getSchema(ns);
+      if (schema != null) {
+        return schema;
+      }
+    }
     return null;
   }
 
@@ -220,22 +265,26 @@ public class SchemaBasedEdmProvider implements CsdlEdmProvider {
 
   @Override
   public List<CsdlAliasInfo> getAliasInfos() throws ODataException {
-    CsdlSchema schema = null;
+    ArrayList<CsdlAliasInfo> list = new ArrayList<CsdlAliasInfo>();
     for (CsdlSchema s : this.edmSchemas) {
-      if (s.getEntityContainer() != null) {
-        schema = s;
-        break;
+      if (s.getAlias() != null) {
+        CsdlAliasInfo ai = new CsdlAliasInfo();
+        ai.setAlias(s.getAlias());
+        ai.setNamespace(s.getNamespace());
+        list.add(ai);
       }
     }
-
-    if (schema == null) {
-      schema = this.edmSchemas.get(0);
+    for(EdmxReference reference:this.references.values()) {
+      for(EdmxReferenceInclude include:reference.getIncludes()) {
+        if (include.getAlias() != null) {
+          CsdlAliasInfo ai = new CsdlAliasInfo();
+          ai.setAlias(include.getAlias());
+          ai.setNamespace(include.getNamespace());
+          list.add(ai);          
+        }
+      }
     }
-
-    CsdlAliasInfo ai = new CsdlAliasInfo();
-    ai.setAlias(schema.getAlias());
-    ai.setNamespace(schema.getNamespace());
-    return Arrays.asList(ai);
+    return list;
   }
 
   @Override
@@ -304,6 +353,33 @@ public class SchemaBasedEdmProvider implements CsdlEdmProvider {
 
   @Override
   public CsdlAnnotations getAnnotationsGroup(FullQualifiedName targetName, String qualifier) throws ODataException {
+    CsdlSchema schema = getSchema(targetName.getNamespace());
+    if (schema != null) {
+      return schema.getAnnotationGroup(targetName.getName(), qualifier);
+    }
     return null;
   }
+
+  void addReferences(ArrayList<EdmxReference> references) {
+    if (references != null && !references.isEmpty()) {
+      for (EdmxReference ref:references) {
+        for (EdmxReferenceInclude include : ref.getIncludes()) {
+          if (include.getAlias() != null) {
+            this.references.put(include.getAlias(), ref);
+          }
+          this.references.put(include.getNamespace(), ref);
+        }
+      }
+    }
+  }
+
+  public void setXMLBase(String base) {
+    if (base != null) {
+      if (base.endsWith("/")) {
+        this.xmlBase = base;
+      } else {
+        this.xmlBase = base+"/";
+      }
+    }
+  }
 }


[04/22] olingo-odata4 git commit: [OLINGO-834] better alias support in URI parser

Posted by mi...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/110c7b0e/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/AliasImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/AliasImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/AliasImpl.java
index f506dc2..07602c2 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/AliasImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/AliasImpl.java
@@ -19,6 +19,7 @@
 package org.apache.olingo.server.core.uri.queryoption.expression;
 
 import org.apache.olingo.server.api.ODataApplicationException;
+import org.apache.olingo.server.api.uri.queryoption.AliasQueryOption;
 import org.apache.olingo.server.api.uri.queryoption.expression.Alias;
 import org.apache.olingo.server.api.uri.queryoption.expression.ExpressionVisitException;
 import org.apache.olingo.server.api.uri.queryoption.expression.ExpressionVisitor;
@@ -26,9 +27,11 @@ import org.apache.olingo.server.api.uri.queryoption.expression.ExpressionVisitor
 public class AliasImpl implements Alias {
 
   private final String parameterName;
+  private final AliasQueryOption alias;
 
-  public AliasImpl(final String parameterName) {
+  public AliasImpl(final String parameterName, final AliasQueryOption alias) {
     this.parameterName = parameterName;
+    this.alias = alias;
   }
 
   @Override
@@ -36,6 +39,10 @@ public class AliasImpl implements Alias {
     return parameterName;
   }
 
+  public AliasQueryOption getAlias() {
+    return alias;
+  }
+
   @Override
   public <T> T accept(final ExpressionVisitor<T> visitor) throws ExpressionVisitException, ODataApplicationException {
     return visitor.visitAlias(parameterName);

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/110c7b0e/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/validator/UriValidationException.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/validator/UriValidationException.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/validator/UriValidationException.java
index 1656150..2b446a7 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/validator/UriValidationException.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/validator/UriValidationException.java
@@ -56,7 +56,9 @@ public class UriValidationException extends ODataLibraryException {
     /** parameter: unallowed resource path */
     UNALLOWED_RESOURCE_PATH,
     /** parameter: missing parameter name */
-    MISSING_PARAMETER;
+    MISSING_PARAMETER,
+    /** parameter: missing alias name */
+    MISSING_ALIAS;
 
     @Override
     public String getKey() {

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/110c7b0e/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/validator/UriValidator.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/validator/UriValidator.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/validator/UriValidator.java
index 5d842fb..cec2fc0 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/validator/UriValidator.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/validator/UriValidator.java
@@ -18,28 +18,22 @@
  */
 package org.apache.olingo.server.core.uri.validator;
 
-import java.util.HashMap;
+import java.util.Collections;
+import java.util.EnumMap;
 import java.util.List;
 import java.util.Map;
 
-import org.apache.olingo.commons.api.edm.EdmEntityType;
 import org.apache.olingo.commons.api.edm.EdmFunction;
-import org.apache.olingo.commons.api.edm.EdmKeyPropertyRef;
-import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
-import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
 import org.apache.olingo.commons.api.edm.EdmProperty;
 import org.apache.olingo.commons.api.edm.EdmReturnType;
 import org.apache.olingo.commons.api.edm.EdmType;
 import org.apache.olingo.commons.api.edm.constants.EdmTypeKind;
 import org.apache.olingo.commons.api.http.HttpMethod;
 import org.apache.olingo.server.api.uri.UriInfo;
-import org.apache.olingo.server.api.uri.UriParameter;
 import org.apache.olingo.server.api.uri.UriResource;
 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.UriResourceKind;
-import org.apache.olingo.server.api.uri.UriResourceNavigation;
 import org.apache.olingo.server.api.uri.UriResourcePartTyped;
 import org.apache.olingo.server.api.uri.UriResourceProperty;
 import org.apache.olingo.server.api.uri.queryoption.SystemQueryOption;
@@ -49,7 +43,7 @@ public class UriValidator {
 
   //@formatter:off (Eclipse formatter)
   //CHECKSTYLE:OFF (Maven checkstyle)
-  private final boolean[][] decisionMatrix =
+  private static final boolean[][] decisionMatrix =
     {
       /*                                          0-FILTER 1-FORMAT 2-EXPAND 3-ID     4-COUNT  5-ORDERBY 6-SEARCH 7-SELECT 8-SKIP   9-SKIPTOKEN 10-TOP */
       /*                              all  0 */ { true ,   true ,   true ,   false,   true ,   true ,    true ,   true ,   true ,   true ,      true  },
@@ -62,7 +56,7 @@ public class UriValidator {
       /*                   entitySetCount  7 */ { true ,   false,   false,   false,   false,   false,    true ,   false,   false,   false,      false },
       /*                           entity  8 */ { false,   true ,   true ,   false,   false,   false,    false,   true ,   false,   false,      false },
       /*                      mediaStream  9 */ { false,   false,   false,   false,   false,   false,    false,   false,   false,   false,      false },
-      /*                       references 10 */ { true ,   true ,   false,   true ,   true ,   true ,    true ,   false,   true ,   true ,      true  },
+      /*                       references 10 */ { true ,   true ,   false,   false,   true ,   true ,    true ,   false,   true ,   true ,      true  },
       /*                        reference 11 */ { false,   true ,   false,   false,   false,   false,    false,   false,   false,   false,      false },
       /*                  propertyComplex 12 */ { false,   true ,   true ,   false,   false,   false,    false,   true ,   false,   false,      false },
       /*        propertyComplexCollection 13 */ { true ,   true ,   true ,   false,   true ,   true ,    false,   true ,   true ,   true ,      true  },
@@ -76,7 +70,7 @@ public class UriValidator {
   //CHECKSTYLE:ON
   //@formatter:on
 
-  private enum RowIndexForUriType {
+  private enum UriType {
     all(0),
     batch(1),
     crossjoin(2),
@@ -100,7 +94,7 @@ public class UriValidator {
 
     private final int idx;
 
-    RowIndexForUriType(final int i) {
+    UriType(final int i) {
       idx = i;
     }
 
@@ -109,308 +103,230 @@ public class UriValidator {
     }
   }
 
-  private enum ColumnIndex {
-    filter(0),
-    format(1),
-    expand(2),
-    id(3),
-    count(4),
-    orderby(5),
-    search(6),
-    select(7),
-    skip(8),
-    skiptoken(9),
-    top(10);
-
-    private final int idx;
-
-    ColumnIndex(final int i) {
-      idx = i;
-    }
-
-    public int getIndex() {
-      return idx;
-    }
+  private static Map<SystemQueryOptionKind, Integer> OPTION_INDEX;
+  static {
+    Map<SystemQueryOptionKind, Integer> temp =
+        new EnumMap<SystemQueryOptionKind, Integer>(SystemQueryOptionKind.class);
+    temp.put(SystemQueryOptionKind.FILTER, 0);
+    temp.put(SystemQueryOptionKind.FORMAT, 1);
+    temp.put(SystemQueryOptionKind.EXPAND, 2);
+    temp.put(SystemQueryOptionKind.ID, 3);
+    temp.put(SystemQueryOptionKind.COUNT, 4);
+    temp.put(SystemQueryOptionKind.ORDERBY, 5);
+    temp.put(SystemQueryOptionKind.SEARCH, 6);
+    temp.put(SystemQueryOptionKind.SELECT, 7);
+    temp.put(SystemQueryOptionKind.SKIP, 8);
+    temp.put(SystemQueryOptionKind.SKIPTOKEN, 9);
+    temp.put(SystemQueryOptionKind.TOP, 10);
+    OPTION_INDEX = Collections.unmodifiableMap(temp);
   }
 
   public void validate(final UriInfo uriInfo, final HttpMethod httpMethod) throws UriValidationException {
-    if (HttpMethod.GET != httpMethod) {
-      validateForHttpMethod(uriInfo, httpMethod);
-    }
-    validateQueryOptions(uriInfo);
-    validateParameters(uriInfo);
-    validateKeyPredicates(uriInfo);
-    validatePropertyOperations(uriInfo, httpMethod);
-  }
-
-  private ColumnIndex colIndex(final SystemQueryOptionKind queryOptionKind) throws UriValidationException {
-    ColumnIndex idx;
-    switch (queryOptionKind) {
-    case FILTER:
-      idx = ColumnIndex.filter;
-      break;
-    case FORMAT:
-      idx = ColumnIndex.format;
-      break;
-    case EXPAND:
-      idx = ColumnIndex.expand;
-      break;
-    case ID:
-      idx = ColumnIndex.id;
-      break;
-    case COUNT:
-      idx = ColumnIndex.count;
-      break;
-    case ORDERBY:
-      idx = ColumnIndex.orderby;
-      break;
-    case SEARCH:
-      idx = ColumnIndex.search;
-      break;
-    case SELECT:
-      idx = ColumnIndex.select;
-      break;
-    case SKIP:
-      idx = ColumnIndex.skip;
-      break;
-    case SKIPTOKEN:
-      idx = ColumnIndex.skiptoken;
-      break;
-    case TOP:
-      idx = ColumnIndex.top;
-      break;
-    default:
-      throw new UriValidationException("Unsupported option: " + queryOptionKind.toString(),
-          UriValidationException.MessageKeys.UNSUPPORTED_QUERY_OPTION, queryOptionKind.toString());
+    final UriType uriType = getUriType(uriInfo);
+    if (HttpMethod.GET == httpMethod) {
+      validateReadQueryOptions(uriType, uriInfo.getSystemQueryOptions());
+    } else {
+      validateNonReadQueryOptions(uriType, isAction(uriInfo), uriInfo.getSystemQueryOptions(), httpMethod);
+      validatePropertyOperations(uriInfo, httpMethod);
     }
-
-    return idx;
   }
 
-  private RowIndexForUriType rowIndexForUriType(final UriInfo uriInfo) throws UriValidationException {
-    RowIndexForUriType idx;
+  private UriType getUriType(final UriInfo uriInfo) throws UriValidationException {
+    UriType uriType;
 
     switch (uriInfo.getKind()) {
     case all:
-      idx = RowIndexForUriType.all;
+      uriType = UriType.all;
       break;
     case batch:
-      idx = RowIndexForUriType.batch;
+      uriType = UriType.batch;
       break;
     case crossjoin:
-      idx = RowIndexForUriType.crossjoin;
+      uriType = UriType.crossjoin;
       break;
     case entityId:
-      idx = RowIndexForUriType.entityId;
+      uriType = UriType.entityId;
       break;
     case metadata:
-      idx = RowIndexForUriType.metadata;
+      uriType = UriType.metadata;
       break;
     case resource:
-      idx = rowIndexForResourceKind(uriInfo);
+      uriType = getUriTypeForResource(uriInfo.getUriResourceParts());
       break;
     case service:
-      idx = RowIndexForUriType.service;
+      uriType = UriType.service;
       break;
     default:
       throw new UriValidationException("Unsupported uriInfo kind: " + uriInfo.getKind(),
           UriValidationException.MessageKeys.UNSUPPORTED_URI_KIND, uriInfo.getKind().toString());
     }
 
-    return idx;
+    return uriType;
   }
 
-  private RowIndexForUriType rowIndexForResourceKind(final UriInfo uriInfo) throws UriValidationException {
-    RowIndexForUriType idx;
-    int lastPathSegmentIndex = uriInfo.getUriResourceParts().size() - 1;
-    UriResource lastPathSegment = uriInfo.getUriResourceParts().get(lastPathSegmentIndex);
+  /**
+   * Determines the URI type for a resource path.
+   * The URI parser has already made sure that there are enough segments for a given type of the last segment,
+   * but don't try to extract always the second-to-last segment, it could cause an {@link IndexOutOfBoundsException}.
+   */
+  private UriType getUriTypeForResource(final List<UriResource> segments) throws UriValidationException {
+    final UriResource lastPathSegment = segments.get(segments.size() - 1);
 
+    UriType uriType;
     switch (lastPathSegment.getKind()) {
     case count:
-      idx = rowIndexForCount(uriInfo);
+      uriType = getUriTypeForCount(segments.get(segments.size() - 2));
       break;
     case action:
-      idx = rowIndexForAction(lastPathSegment);
+      uriType = getUriTypeForAction(lastPathSegment);
       break;
     case complexProperty:
-      idx = rowIndexForComplexProperty(lastPathSegment);
+      uriType = getUriTypeForComplexProperty(lastPathSegment);
       break;
     case entitySet:
     case navigationProperty:
-      idx = rowIndexForEntitySet(lastPathSegment);
+      uriType = getUriTypeForEntitySet(lastPathSegment);
       break;
     case function:
-      idx = rowIndexForFunction(lastPathSegment);
+      uriType = getUriTypeForFunction(lastPathSegment);
       break;
     case primitiveProperty:
-      idx = rowIndexForPrimitiveProperty(lastPathSegment);
+      uriType = getUriTypeForPrimitiveProperty(lastPathSegment);
       break;
     case ref:
-      idx = rowIndexForRef(uriInfo, lastPathSegment);
-      break;
-    case root:
-      idx = RowIndexForUriType.service;
+      uriType = getUriTypeForRef(segments.get(segments.size() - 2));
       break;
     case singleton:
-      idx = RowIndexForUriType.entity;
+      uriType = UriType.entity;
       break;
     case value:
-      idx = rowIndexForValue(uriInfo);
+      uriType = getUriTypeForValue(segments.get(segments.size() - 2));
       break;
     default:
       throw new UriValidationException("Unsupported uriResource kind: " + lastPathSegment.getKind(),
           UriValidationException.MessageKeys.UNSUPPORTED_URI_RESOURCE_KIND, lastPathSegment.getKind().toString());
     }
 
-    return idx;
+    return uriType;
   }
 
-  private RowIndexForUriType rowIndexForValue(final UriInfo uriInfo) throws UriValidationException {
-    RowIndexForUriType idx;
-    int secondLastPathSegmentIndex = uriInfo.getUriResourceParts().size() - 2;
-    UriResource secondLastPathSegment = uriInfo.getUriResourceParts().get(secondLastPathSegmentIndex);
-
+  private UriType getUriTypeForValue(final UriResource secondLastPathSegment) throws UriValidationException {
+    UriType uriType;
     switch (secondLastPathSegment.getKind()) {
     case primitiveProperty:
-      idx = RowIndexForUriType.propertyPrimitiveValue;
+      uriType = UriType.propertyPrimitiveValue;
       break;
     case entitySet:
     case navigationProperty:
     case singleton:
-      idx = RowIndexForUriType.mediaStream;
+      uriType = UriType.mediaStream;
       break;
     case function:
       UriResourceFunction uriFunction = (UriResourceFunction) secondLastPathSegment;
       final EdmFunction function = uriFunction.getFunction();
-      idx = function.getReturnType().getType().getKind() == EdmTypeKind.ENTITY ?
-          RowIndexForUriType.mediaStream : RowIndexForUriType.propertyPrimitiveValue;
+      uriType = function.getReturnType().getType().getKind() == EdmTypeKind.ENTITY ?
+          UriType.mediaStream : UriType.propertyPrimitiveValue;
       break;
     default:
       throw new UriValidationException(
           "Unexpected kind in path segment before $value: " + secondLastPathSegment.getKind(),
           UriValidationException.MessageKeys.UNALLOWED_KIND_BEFORE_VALUE, secondLastPathSegment.toString());
     }
-    return idx;
+    return uriType;
   }
 
-  private RowIndexForUriType rowIndexForRef(final UriInfo uriInfo, final UriResource lastPathSegment)
-      throws UriValidationException {
-    int secondLastPathSegmentIndex = uriInfo.getUriResourceParts().size() - 2;
-    UriResource secondLastPathSegment = uriInfo.getUriResourceParts().get(secondLastPathSegmentIndex);
+  private UriType getUriTypeForRef(final UriResource secondLastPathSegment) throws UriValidationException {
+    return isCollection(secondLastPathSegment) ? UriType.references : UriType.reference;
+  }
 
-    if (secondLastPathSegment instanceof UriResourcePartTyped) {
-      return ((UriResourcePartTyped) secondLastPathSegment).isCollection() ?
-          RowIndexForUriType.references : RowIndexForUriType.reference;
+  private boolean isCollection(final UriResource pathSegment) throws UriValidationException {
+    if (pathSegment instanceof UriResourcePartTyped) {
+      return ((UriResourcePartTyped) pathSegment).isCollection();
     } else {
       throw new UriValidationException(
-          "secondLastPathSegment not a class of UriResourcePartTyped: " + lastPathSegment.getClass(),
-          UriValidationException.MessageKeys.LAST_SEGMENT_NOT_TYPED, lastPathSegment.toString());
+          "Path segment is not an instance of UriResourcePartTyped but " + pathSegment.getClass(),
+          UriValidationException.MessageKeys.LAST_SEGMENT_NOT_TYPED, pathSegment.toString());
     }
   }
 
-  private RowIndexForUriType rowIndexForPrimitiveProperty(final UriResource lastPathSegment)
-      throws UriValidationException {
-    if (lastPathSegment instanceof UriResourcePartTyped) {
-      return ((UriResourcePartTyped) lastPathSegment).isCollection() ?
-          RowIndexForUriType.propertyPrimitiveCollection : RowIndexForUriType.propertyPrimitive;
-    } else {
-      throw new UriValidationException(
-          "lastPathSegment not a class of UriResourcePartTyped: " + lastPathSegment.getClass(),
-          UriValidationException.MessageKeys.LAST_SEGMENT_NOT_TYPED, lastPathSegment.toString());
-    }
+  private UriType getUriTypeForPrimitiveProperty(final UriResource lastPathSegment) throws UriValidationException {
+    return isCollection(lastPathSegment) ? UriType.propertyPrimitiveCollection : UriType.propertyPrimitive;
   }
 
-  private RowIndexForUriType rowIndexForFunction(final UriResource lastPathSegment) throws UriValidationException {
+  private UriType getUriTypeForFunction(final UriResource lastPathSegment) throws UriValidationException {
     final UriResourceFunction uriFunction = (UriResourceFunction) lastPathSegment;
     if (!uriFunction.getFunction().isComposable()) {
-      return RowIndexForUriType.none;
+      return UriType.none;
     }
 
     final boolean isCollection = uriFunction.isCollection();
     final EdmTypeKind typeKind = uriFunction.getFunction().getReturnType().getType().getKind();
-    RowIndexForUriType idx;
+    UriType uriType;
     switch (typeKind) {
     case ENTITY:
-      idx = isCollection ? RowIndexForUriType.entitySet : RowIndexForUriType.entity;
+      uriType = isCollection ? UriType.entitySet : UriType.entity;
       break;
     case PRIMITIVE:
     case ENUM:
     case DEFINITION:
-      idx = isCollection ? RowIndexForUriType.propertyPrimitiveCollection : RowIndexForUriType.propertyPrimitive;
+      uriType = isCollection ? UriType.propertyPrimitiveCollection : UriType.propertyPrimitive;
       break;
     case COMPLEX:
-      idx = isCollection ? RowIndexForUriType.propertyComplexCollection : RowIndexForUriType.propertyComplex;
+      uriType = isCollection ? UriType.propertyComplexCollection : UriType.propertyComplex;
       break;
     default:
       throw new UriValidationException("Unsupported function return type: " + typeKind,
           UriValidationException.MessageKeys.UNSUPPORTED_FUNCTION_RETURN_TYPE, typeKind.toString());
     }
 
-    return idx;
+    return uriType;
   }
 
-  private RowIndexForUriType rowIndexForEntitySet(final UriResource lastPathSegment) throws UriValidationException {
-    if (lastPathSegment instanceof UriResourcePartTyped) {
-      return ((UriResourcePartTyped) lastPathSegment).isCollection() ?
-          RowIndexForUriType.entitySet : RowIndexForUriType.entity;
-    } else {
-      throw new UriValidationException("lastPathSegment not a class of UriResourcePartTyped: "
-          + lastPathSegment.getClass(), UriValidationException.MessageKeys.LAST_SEGMENT_NOT_TYPED,
-          lastPathSegment.toString());
-    }
+  private UriType getUriTypeForEntitySet(final UriResource lastPathSegment) throws UriValidationException {
+    return isCollection(lastPathSegment) ? UriType.entitySet : UriType.entity;
   }
 
-  private RowIndexForUriType rowIndexForComplexProperty(final UriResource lastPathSegment)
-      throws UriValidationException {
-    if (lastPathSegment instanceof UriResourcePartTyped) {
-      return ((UriResourcePartTyped) lastPathSegment).isCollection() ?
-          RowIndexForUriType.propertyComplexCollection : RowIndexForUriType.propertyComplex;
-    } else {
-      throw new UriValidationException("lastPathSegment not a class of UriResourcePartTyped: "
-          + lastPathSegment.getClass(), UriValidationException.MessageKeys.LAST_SEGMENT_NOT_TYPED,
-          lastPathSegment.toString());
-    }
+  private UriType getUriTypeForComplexProperty(final UriResource lastPathSegment) throws UriValidationException {
+    return isCollection(lastPathSegment) ? UriType.propertyComplexCollection : UriType.propertyComplex;
   }
 
-  private RowIndexForUriType rowIndexForAction(final UriResource lastPathSegment) throws UriValidationException {
+  private UriType getUriTypeForAction(final UriResource lastPathSegment) throws UriValidationException {
     final EdmReturnType rt = ((UriResourceAction) lastPathSegment).getAction().getReturnType();
     if (rt == null) {
-      return RowIndexForUriType.none;
+      return UriType.none;
     }
-    RowIndexForUriType idx;
+    UriType uriType;
     switch (rt.getType().getKind()) {
     case ENTITY:
-      idx = rt.isCollection() ? RowIndexForUriType.entitySet : RowIndexForUriType.entity;
+      uriType = rt.isCollection() ? UriType.entitySet : UriType.entity;
       break;
     case PRIMITIVE:
     case ENUM:
     case DEFINITION:
-      idx = rt.isCollection() ? RowIndexForUriType.propertyPrimitiveCollection : RowIndexForUriType.propertyPrimitive;
+      uriType = rt.isCollection() ? UriType.propertyPrimitiveCollection : UriType.propertyPrimitive;
       break;
     case COMPLEX:
-      idx = rt.isCollection() ? RowIndexForUriType.propertyComplexCollection : RowIndexForUriType.propertyComplex;
+      uriType = rt.isCollection() ? UriType.propertyComplexCollection : UriType.propertyComplex;
       break;
     default:
       throw new UriValidationException("Unsupported action return type: " + rt.getType().getKind(),
           UriValidationException.MessageKeys.UNSUPPORTED_ACTION_RETURN_TYPE, rt.getType().getKind().toString());
     }
-    return idx;
+    return uriType;
   }
 
-  private RowIndexForUriType rowIndexForCount(final UriInfo uriInfo) throws UriValidationException {
-    RowIndexForUriType idx;
-    int secondLastPathSegmentIndex = uriInfo.getUriResourceParts().size() - 2;
-    UriResource secondLastPathSegment = uriInfo.getUriResourceParts().get(secondLastPathSegmentIndex);
+  private UriType getUriTypeForCount(final UriResource secondLastPathSegment) throws UriValidationException {
+    UriType uriType;
     switch (secondLastPathSegment.getKind()) {
     case entitySet:
     case navigationProperty:
-      idx = RowIndexForUriType.entitySetCount;
+      uriType = UriType.entitySetCount;
       break;
     case complexProperty:
-      idx = RowIndexForUriType.propertyComplexCollectionCount;
+      uriType = UriType.propertyComplexCollectionCount;
       break;
     case primitiveProperty:
-      idx = RowIndexForUriType.propertyPrimitiveCollectionCount;
+      uriType = UriType.propertyPrimitiveCollectionCount;
       break;
     case function:
       final UriResourceFunction uriFunction = (UriResourceFunction) secondLastPathSegment;
@@ -418,15 +334,15 @@ public class UriValidator {
       final EdmType returnType = function.getReturnType().getType();
       switch (returnType.getKind()) {
       case ENTITY:
-        idx = RowIndexForUriType.entitySetCount;
+        uriType = UriType.entitySetCount;
         break;
       case COMPLEX:
-        idx = RowIndexForUriType.propertyComplexCollectionCount;
+        uriType = UriType.propertyComplexCollectionCount;
         break;
       case PRIMITIVE:
       case ENUM:
       case DEFINITION:
-        idx = RowIndexForUriType.propertyPrimitiveCollectionCount;
+        uriType = UriType.propertyPrimitiveCollectionCount;
         break;
       default:
         throw new UriValidationException("Unsupported return type: " + returnType.getKind(),
@@ -438,80 +354,54 @@ public class UriValidator {
           UriValidationException.MessageKeys.UNALLOWED_KIND_BEFORE_COUNT, secondLastPathSegment.toString());
     }
 
-    return idx;
+    return uriType;
   }
 
-  private void validateQueryOptions(final UriInfo uriInfo) throws UriValidationException {
-    RowIndexForUriType row = rowIndexForUriType(uriInfo);
-
-    for (SystemQueryOption option : uriInfo.getSystemQueryOptions()) {
-      ColumnIndex col = colIndex(option.getKind());
-
-      if (!decisionMatrix[row.getIndex()][col.getIndex()]) {
-        throw new UriValidationException("System query option not allowed: " + option.getName(),
-            UriValidationException.MessageKeys.SYSTEM_QUERY_OPTION_NOT_ALLOWED, option.getName());
-      }
-    }
-  }
-
-  private void validateForHttpMethod(final UriInfo uriInfo, final HttpMethod httpMethod) throws UriValidationException {
-    switch (httpMethod) {
-    case POST:
-      if (!isAction(uriInfo)) {
-        // POST and SystemQueryOptions only allowed if addressed resource is an action
-        validateNoQueryOptionsForHttpMethod(uriInfo, httpMethod);
-      }
-      break;
-    case DELETE:
-      if (!isReferences(uriInfo)) {
-        // DELETE and SystemQueryOptions only allowed if addressed resource is a reference collection
-        validateNoQueryOptionsForHttpMethod(uriInfo, httpMethod);
-      } else {
-        // Only $id allowed as SystemQueryOption for DELETE and references
-        for (SystemQueryOption option : uriInfo.getSystemQueryOptions()) {
-          if (SystemQueryOptionKind.ID != option.getKind()) {
-            throw new UriValidationException(
-                "System query option " + option.getName() + " not allowed for method " + httpMethod,
-                UriValidationException.MessageKeys.SYSTEM_QUERY_OPTION_NOT_ALLOWED_FOR_HTTP_METHOD,
-                option.getName(), httpMethod.toString());
-          }
+  private void validateReadQueryOptions(final UriType uriType, final List<SystemQueryOption> options)
+      throws UriValidationException {
+    for (final SystemQueryOption option : options) {
+      final SystemQueryOptionKind kind = option.getKind();
+      if (OPTION_INDEX.containsKey(kind)) {
+        final int columnIndex = OPTION_INDEX.get(kind);
+        if (!decisionMatrix[uriType.getIndex()][columnIndex]) {
+          throw new UriValidationException("System query option not allowed: " + option.getName(),
+              UriValidationException.MessageKeys.SYSTEM_QUERY_OPTION_NOT_ALLOWED, option.getName());
         }
+      } else {
+        throw new UriValidationException("Unsupported option: " + kind,
+            UriValidationException.MessageKeys.UNSUPPORTED_QUERY_OPTION, kind.toString());
       }
-      break;
-    case PUT:
-    case PATCH:
-      // PUT and PATCH do not allow system query options
-      validateNoQueryOptionsForHttpMethod(uriInfo, httpMethod);
-      break;
-    default:
-      throw new UriValidationException("HTTP method not supported: " + httpMethod,
-          UriValidationException.MessageKeys.UNSUPPORTED_HTTP_METHOD, httpMethod.toString());
     }
-
   }
 
-  private boolean isReferences(final UriInfo uriInfo) {
-    if (!uriInfo.getSystemQueryOptions().isEmpty()) {
-      List<UriResource> uriResourceParts = uriInfo.getUriResourceParts();
-      if (UriResourceKind.ref == uriResourceParts.get(uriResourceParts.size() - 1).getKind()) {
-        UriResourcePartTyped previousSegment = (UriResourcePartTyped) uriResourceParts.get(uriResourceParts.size() - 2);
-        return previousSegment.isCollection();
+  private void validateNonReadQueryOptions(final UriType uriType, final boolean isAction,
+      final List<SystemQueryOption> options, final HttpMethod httpMethod) throws UriValidationException {
+    if (httpMethod == HttpMethod.POST && isAction) {
+      // From the OData specification:
+      // For POST requests to an action URL the return type of the action determines the applicable
+      // system query options that a service MAY support, following the same rules as GET requests.
+      validateReadQueryOptions(uriType, options);
+
+    } else if (httpMethod == HttpMethod.DELETE && uriType == UriType.references) {
+      // Only $id is allowed as SystemQueryOption for DELETE on a reference collection.
+      for (final SystemQueryOption option : options) {
+        if (SystemQueryOptionKind.ID != option.getKind()) {
+          throw new UriValidationException(
+              "System query option " + option.getName() + " is not allowed for method " + httpMethod,
+              UriValidationException.MessageKeys.SYSTEM_QUERY_OPTION_NOT_ALLOWED_FOR_HTTP_METHOD,
+              option.getName(), httpMethod.toString());
+        }
       }
-    }
-    return false;
-  }
 
-  private void validateNoQueryOptionsForHttpMethod(final UriInfo uriInfo, final HttpMethod httpMethod)
-      throws UriValidationException {
-    if (!uriInfo.getSystemQueryOptions().isEmpty()) {
-      StringBuilder options = new StringBuilder();
-      for (SystemQueryOption option : uriInfo.getSystemQueryOptions()) {
-        options.append(option.getName()).append(" ");
+    } else if (!options.isEmpty()) {
+      StringBuilder optionsString = new StringBuilder();
+      for (final SystemQueryOption option : options) {
+        optionsString.append(option.getName()).append(' ');
       }
       throw new UriValidationException(
-          "System query option " + options.toString() + " not allowed for method " + httpMethod,
+          "System query option(s) " + optionsString.toString() + "not allowed for method " + httpMethod,
           UriValidationException.MessageKeys.SYSTEM_QUERY_OPTION_NOT_ALLOWED_FOR_HTTP_METHOD,
-          options.toString(), httpMethod.toString());
+          optionsString.toString(), httpMethod.toString());
     }
   }
 
@@ -521,139 +411,6 @@ public class UriValidator {
         && UriResourceKind.action == uriResourceParts.get(uriResourceParts.size() - 1).getKind();
   }
 
-  private void validateParameters(final UriInfo uriInfo) throws UriValidationException {
-    for (UriResource pathSegment : uriInfo.getUriResourceParts()) {
-      final boolean isFunction = pathSegment.getKind() == UriResourceKind.function;
-
-      if (isFunction) {
-        final UriResourceFunction functionPathSegment = (UriResourceFunction) pathSegment;
-        final EdmFunction edmFunction = functionPathSegment.getFunction();
-
-        final Map<String, UriParameter> parameters = new HashMap<String, UriParameter>();
-        for (final UriParameter parameter : functionPathSegment.getParameters()) {
-          parameters.put(parameter.getName(), parameter);
-        }
-
-        boolean firstParameter = true;
-        for (final String parameterName : edmFunction.getParameterNames()) {
-          final UriParameter parameter = parameters.get(parameterName);
-          final boolean isNullable = edmFunction.getParameter(parameterName).isNullable();
-
-          if (parameter != null) {
-            /** No alias, value explicit null */
-            if (parameter.getText() == null
-                && parameter.getAlias() == null && !isNullable) {
-              throw new UriValidationException("Missing non nullable parameter " + parameterName,
-                  UriValidationException.MessageKeys.MISSING_PARAMETER, parameterName);
-            } else if (parameter.getText() == null && parameter.getAlias() != null) {
-              final String valueForAlias = uriInfo.getValueForAlias(parameter.getAlias());
-              /** Alias value is missing or explicit null **/
-              if (valueForAlias == null && !isNullable) {
-                throw new UriValidationException("Missing non nullable parameter " + parameterName,
-                    UriValidationException.MessageKeys.MISSING_PARAMETER, parameterName);
-              }
-            }
-
-            parameters.remove(parameterName);
-          } else if (!isNullable && !(firstParameter && edmFunction.isBound())) {
-            // The first parameter of bound functions is implicit provided by the preceding path segment
-            throw new UriValidationException("Missing non nullable parameter " + parameterName,
-                UriValidationException.MessageKeys.MISSING_PARAMETER, parameterName);
-          }
-
-          firstParameter = false;
-        }
-
-        if (!parameters.isEmpty()) {
-          final String parameterName = parameters.keySet().iterator().next();
-          throw new UriValidationException("Unsupported parameter " + parameterName,
-              UriValidationException.MessageKeys.UNSUPPORTED_PARAMETER, parameterName);
-        }
-      }
-    }
-  }
-
-  private void validateKeyPredicates(final UriInfo uriInfo) throws UriValidationException {
-    for (UriResource pathSegment : uriInfo.getUriResourceParts()) {
-      final boolean isEntitySet = pathSegment.getKind() == UriResourceKind.entitySet;
-      final boolean isEntityColFunction = isEntityColFunction(pathSegment);
-
-      if (isEntitySet || pathSegment.getKind() == UriResourceKind.navigationProperty || isEntityColFunction) {
-        final List<UriParameter> keyPredicates = isEntitySet ?
-            ((UriResourceEntitySet) pathSegment).getKeyPredicates() :
-            isEntityColFunction ?
-                ((UriResourceFunction) pathSegment).getKeyPredicates() :
-                ((UriResourceNavigation) pathSegment).getKeyPredicates();
-
-        if (keyPredicates != null) {
-                final EdmEntityType entityType = isEntitySet ?
-                    ((UriResourceEntitySet) pathSegment).getEntityType() :
-                      isEntityColFunction ? (EdmEntityType) ((UriResourceFunction) pathSegment).getType()
-                  : (EdmEntityType) ((UriResourceNavigation) pathSegment).getType();
-                      final List<String> keyPredicateNames = entityType.getKeyPredicateNames();
-                      Map<String, EdmKeyPropertyRef> edmKeys = new HashMap<String, EdmKeyPropertyRef>();
-                      for (EdmKeyPropertyRef key : entityType.getKeyPropertyRefs()) {
-                        edmKeys.put(key.getName(), key);
-                        final String alias = key.getAlias();
-                        if (alias != null) {
-                          edmKeys.put(alias, key);
-                        }
-                      }
-
-                      for (UriParameter keyPredicate : keyPredicates) {
-                        final String name = keyPredicate.getName();
-                        final String alias = keyPredicate.getAlias();
-
-                        if (keyPredicate.getReferencedProperty() == null) {
-                          final String value = alias == null ?
-                              keyPredicate.getText() :
-                                uriInfo.getValueForAlias(alias);
-
-                              EdmKeyPropertyRef edmKey = edmKeys.get(name);
-                              if (edmKey == null) {
-                                if (keyPredicateNames.contains(name)) {
-                                  throw new UriValidationException("Double key property: " + name,
-                                      UriValidationException.MessageKeys.DOUBLE_KEY_PROPERTY, name);
-                                } else {
-                                  throw new UriValidationException("Unknown key property: " + name,
-                                      UriValidationException.MessageKeys.INVALID_KEY_PROPERTY, name);
-                                }
-                              }
-
-                              final EdmProperty property = edmKey.getProperty();
-                              final EdmPrimitiveType edmPrimitiveType = (EdmPrimitiveType) property.getType();
-                              try {
-                                if (!edmPrimitiveType.validate(edmPrimitiveType.fromUriLiteral(value),
-                                    property.isNullable(), property.getMaxLength(),
-                                    property.getPrecision(), property.getScale(), property.isUnicode())) {
-                                  throw new UriValidationException("PrimitiveTypeException",
-                                      UriValidationException.MessageKeys.INVALID_KEY_PROPERTY, name);
-                                }
-                              } catch (EdmPrimitiveTypeException e) {
-                                throw new UriValidationException("PrimitiveTypeException", e,
-                                    UriValidationException.MessageKeys.INVALID_KEY_PROPERTY, name);
-                              }
-                        }
-
-                        edmKeys.remove(name);
-                        edmKeys.remove(alias);
-                      }
-              }
-      }
-    }
-  }
-
-  private boolean isEntityColFunction(final UriResource pathSegment) {
-    if (pathSegment.getKind() == UriResourceKind.function) {
-      final UriResourceFunction resourceFunction = (UriResourceFunction) pathSegment;
-      final EdmReturnType returnType = resourceFunction.getFunction().getReturnType();
-
-      return returnType.isCollection() && returnType.getType().getKind() == EdmTypeKind.ENTITY;
-    } else {
-      return false;
-    }
-  }
-
   private void validatePropertyOperations(final UriInfo uriInfo, final HttpMethod method)
       throws UriValidationException {
     final List<UriResource> parts = uriInfo.getUriResourceParts();

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/110c7b0e/lib/server-core/src/main/resources/server-core-exceptions-i18n.properties
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/resources/server-core-exceptions-i18n.properties b/lib/server-core/src/main/resources/server-core-exceptions-i18n.properties
index 6bbad3b..ef5e744 100644
--- a/lib/server-core/src/main/resources/server-core-exceptions-i18n.properties
+++ b/lib/server-core/src/main/resources/server-core-exceptions-i18n.properties
@@ -89,6 +89,7 @@ UriValidationException.UNALLOWED_KIND_BEFORE_VALUE=The kind '%1$s' is not allowe
 UriValidationException.UNALLOWED_KIND_BEFORE_COUNT=The kind '%1$s' is not allowed before '$count'.
 UriValidationException.UNALLOWED_RESOURCE_PATH=The resource part '%1$s' is not allowed.
 UriValidationException.MISSING_PARAMETER=Missing mandatory parameter '%1$s'.
+UriValidationException.MISSING_ALIAS=Missing alias '%1$s'.
 
 ContentNegotiatorException.UNSUPPORTED_ACCEPT_TYPES=The content-type range '%1$s' is not supported as value of the Accept header.
 ContentNegotiatorException.UNSUPPORTED_CONTENT_TYPE=The content type '%1$s' is not supported.

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/110c7b0e/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/UriInfoImplTest.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/UriInfoImplTest.java b/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/UriInfoImplTest.java
index 68e6637..bdc2986 100644
--- a/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/UriInfoImplTest.java
+++ b/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/UriInfoImplTest.java
@@ -23,8 +23,6 @@ import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
-import java.util.Arrays;
-
 import org.apache.olingo.commons.api.edm.EdmAction;
 import org.apache.olingo.commons.api.edm.EdmEntityType;
 import org.apache.olingo.commons.api.ex.ODataRuntimeException;
@@ -122,31 +120,30 @@ public class UriInfoImplTest {
     final QueryOption top = new TopOptionImpl().setName("");
     final QueryOption levels = new LevelsOptionImpl().setName("");
 
-    final QueryOption customOption0 = new CustomQueryOptionImpl().setName("").setText("A");
-    final QueryOption customOption1 = new CustomQueryOptionImpl().setName("").setText("B");
+    final QueryOption customOption0 = new CustomQueryOptionImpl().setName("0").setText("A");
+    final QueryOption customOption1 = new CustomQueryOptionImpl().setName("1").setText("B");
 
     final QueryOption initialQueryOption = new CustomQueryOptionImpl();
 
     final QueryOption alias = new AliasQueryOptionImpl().setName("alias").setText("C");
 
     final UriInfo uriInfo = new UriInfoImpl()
-        .setQueryOptions(Arrays.asList(
-            expand,
-            filter,
-            format,
-            id,
-            inlinecount,
-            orderby,
-            search,
-            select,
-            skip,
-            skipToken,
-            top,
-            customOption0,
-            customOption1,
-            levels,
-            initialQueryOption,
-            alias));
+        .setQueryOption(expand)
+        .setQueryOption(filter)
+        .setQueryOption(format)
+        .setQueryOption(id)
+        .setQueryOption(inlinecount)
+        .setQueryOption(orderby)
+        .setQueryOption(search)
+        .setQueryOption(select)
+        .setQueryOption(skip)
+        .setQueryOption(skipToken)
+        .setQueryOption(top)
+        .setQueryOption(customOption0)
+        .setQueryOption(customOption1)
+        .setQueryOption(levels)
+        .setQueryOption(initialQueryOption)
+        .setQueryOption(alias);
 
     assertEquals(12, uriInfo.getSystemQueryOptions().size());
     assertEquals(expand, uriInfo.getExpandOption());
@@ -164,7 +161,7 @@ public class UriInfoImplTest {
     assertArrayEquals(new QueryOption[] { alias }, uriInfo.getAliases().toArray());
     assertEquals("C", uriInfo.getValueForAlias("alias"));
 
-    assertArrayEquals(new QueryOption[] { customOption0, customOption1, initialQueryOption },
+    assertArrayEquals(new QueryOption[] { customOption0, customOption1 },
         uriInfo.getCustomQueryOptions().toArray());
   }
 
@@ -185,7 +182,6 @@ public class UriInfoImplTest {
   @Test
   public void alias() {
     final UriInfo uriInfo = new UriInfoImpl()
-        .addAlias((AliasQueryOption) new AliasQueryOptionImpl().setName("A").setText("notUsed"))
         .addAlias((AliasQueryOption) new AliasQueryOptionImpl().setName("A").setText("X"))
         .addAlias((AliasQueryOption) new AliasQueryOptionImpl().setName("B").setText("Y"))
         .addAlias((AliasQueryOption) new AliasQueryOptionImpl().setName("C").setText("Z"));
@@ -199,4 +195,12 @@ public class UriInfoImplTest {
     assertTrue(uriInfo.getSystemQueryOptions().isEmpty());
     assertTrue(uriInfo.getCustomQueryOptions().isEmpty());
   }
+
+  @Test(expected = ODataRuntimeException.class)
+  public void doubleAlias() {
+    final AliasQueryOption alias = (AliasQueryOption) new AliasQueryOptionImpl().setName("A");
+    new UriInfoImpl()
+        .addAlias(alias)
+        .addAlias(alias);
+  }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/110c7b0e/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/ExpressionParserTest.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/ExpressionParserTest.java b/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/ExpressionParserTest.java
index a5fda50..1fce7b5 100644
--- a/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/ExpressionParserTest.java
+++ b/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/ExpressionParserTest.java
@@ -252,7 +252,7 @@ public class ExpressionParserTest {
   private Expression parseExpression(final String expressionString)
       throws UriParserException, UriValidationException {
     UriTokenizer tokenizer = new UriTokenizer(expressionString);
-    final Expression expression = new ExpressionParser(mock(Edm.class), odata).parse(tokenizer, null, null);
+    final Expression expression = new ExpressionParser(mock(Edm.class), odata).parse(tokenizer, null, null, null);
     assertNotNull(expression);
     assertTrue(tokenizer.next(TokenKind.EOF));
     return expression;

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/110c7b0e/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/UriTokenizerTest.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/UriTokenizerTest.java b/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/UriTokenizerTest.java
index 3ca49c8..118e2ea 100644
--- a/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/UriTokenizerTest.java
+++ b/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/UriTokenizerTest.java
@@ -371,6 +371,9 @@ public class UriTokenizerTest {
     assertTrue(new UriTokenizer("{\"name\":null}").next(TokenKind.jsonArrayOrObject));
     assertTrue(new UriTokenizer("{\"name\":\"value\"}").next(TokenKind.jsonArrayOrObject));
     assertTrue(new UriTokenizer("{\"name\":\"value\",\"name2\":null}").next(TokenKind.jsonArrayOrObject));
+    assertFalse(new UriTokenizer("{\"name\"}").next(TokenKind.jsonArrayOrObject));
+    assertFalse(new UriTokenizer("{\"name\":}").next(TokenKind.jsonArrayOrObject));
+    assertFalse(new UriTokenizer("{0}").next(TokenKind.jsonArrayOrObject));
 
     // array with values
     assertTrue(new UriTokenizer("[]").next(TokenKind.jsonArrayOrObject));

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/110c7b0e/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataProvider.java
----------------------------------------------------------------------
diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataProvider.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataProvider.java
index 20cbf94..9dad2b9 100644
--- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataProvider.java
+++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataProvider.java
@@ -62,6 +62,7 @@ import org.apache.olingo.server.api.serializer.SerializerException;
 import org.apache.olingo.server.api.uri.UriInfoResource;
 import org.apache.olingo.server.api.uri.UriParameter;
 import org.apache.olingo.server.api.uri.UriResourceEntitySet;
+import org.apache.olingo.server.api.uri.queryoption.expression.Literal;
 
 public class DataProvider {
 
@@ -104,7 +105,12 @@ public class DataProvider {
           final EdmProperty property = (EdmProperty) edmEntityType.getProperty(key.getName());
           final EdmPrimitiveType type = (EdmPrimitiveType) property.getType();
           final Object value = entity.getProperty(key.getName()).getValue();
-          final Object keyValue = type.valueOfString(type.fromUriLiteral(key.getText()),
+          if (key.getExpression() != null && !(key.getExpression() instanceof Literal)) {
+            throw new DataProviderException("Expression in key value is not supported yet!",
+                HttpStatusCode.NOT_IMPLEMENTED);
+          }
+          final String text = key.getAlias() == null ? key.getText() : ((Literal) key.getExpression()).getText();
+          final Object keyValue = type.valueOfString(type.fromUriLiteral(text),
               property.isNullable(), property.getMaxLength(), property.getPrecision(), property.getScale(),
               property.isUnicode(),
               Calendar.class.isAssignableFrom(value.getClass()) ? Calendar.class : value.getClass());
@@ -540,6 +546,10 @@ public class DataProvider {
       final List<UriParameter> parameters, final UriInfoResource uriInfo) throws DataProviderException {
     Map<String, Parameter> values = new HashMap<String, Parameter>();
     for (final UriParameter parameter : parameters) {
+      if (parameter.getExpression() != null && !(parameter.getExpression() instanceof Literal)) {
+        throw new DataProviderException("Expression in function-parameter value is not supported yet!",
+            HttpStatusCode.NOT_IMPLEMENTED);
+      }
       final EdmParameter edmParameter = function.getParameter(parameter.getName());
       final String text = parameter.getAlias() == null ?
           parameter.getText() :

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/110c7b0e/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/options/SystemQueryOptionsRuntimeException.java
----------------------------------------------------------------------
diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/options/SystemQueryOptionsRuntimeException.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/options/SystemQueryOptionsRuntimeException.java
index 469052d..9b74378 100644
--- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/options/SystemQueryOptionsRuntimeException.java
+++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/options/SystemQueryOptionsRuntimeException.java
@@ -18,13 +18,14 @@
  */
 package org.apache.olingo.server.tecsvc.processor.queryoptions.options;
 
+import org.apache.olingo.commons.api.ex.ODataException;
 import org.apache.olingo.commons.api.ex.ODataRuntimeException;
 
 public class SystemQueryOptionsRuntimeException extends ODataRuntimeException {
 
   private static final long serialVersionUID = 1L;
 
-  public SystemQueryOptionsRuntimeException(final Exception cause) {
+  public SystemQueryOptionsRuntimeException(final ODataException cause) {
     super(cause);
   }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/110c7b0e/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/ContainerProvider.java
----------------------------------------------------------------------
diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/ContainerProvider.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/ContainerProvider.java
index 3fc164e..aeeb167 100644
--- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/ContainerProvider.java
+++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/ContainerProvider.java
@@ -206,7 +206,7 @@ public class ContainerProvider {
             .setAnnotations(Arrays.asList(
                 new CsdlAnnotation().setTerm("Core.Description")
                     .setExpression(new CsdlConstantExpression(CsdlConstantExpression.ConstantExpressionType.String)
-                        .setValue("Contains entities with two primitve types")),
+                        .setValue("Contains entities with two primitive types")),
                 new CsdlAnnotation().setTerm(TermProvider.TERM_DATA.getFullQualifiedNameAsString()).setExpression(
                     new CsdlConstantExpression(CsdlConstantExpression.ConstantExpressionType.Bool, "true"))));
       } else if (name.equals("ESMixPrimCollComp")) {
@@ -217,7 +217,7 @@ public class ContainerProvider {
                 new CsdlAnnotation().setTerm("Core.Description")
                     .setExpression(new CsdlConstantExpression(CsdlConstantExpression.ConstantExpressionType.String)
                         .setValue("Contains entities with various properties of type primitive, collection "
-                            + "of primitve, complex and collection of complex")),
+                            + "of primitive, complex and collection of complex")),
                 new CsdlAnnotation().setTerm(TermProvider.TERM_DATA.getFullQualifiedNameAsString()).setExpression(
                     new CsdlConstantExpression(CsdlConstantExpression.ConstantExpressionType.Bool, "true"))));
 
@@ -609,7 +609,7 @@ public class ContainerProvider {
                 new CsdlAnnotation().setTerm("Core.Description")
                     .setExpression(new CsdlConstantExpression(CsdlConstantExpression.ConstantExpressionType.String)
                         .setValue("Contains entities with a complex type, "
-                            + "various nested primitve types and collections")),
+                            + "various nested primitive types and collections")),
                 new CsdlAnnotation().setTerm(TermProvider.TERM_DATA.getFullQualifiedNameAsString()).setExpression(
                     new CsdlConstantExpression(CsdlConstantExpression.ConstantExpressionType.Bool, "true"))));
 

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/110c7b0e/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/parser/TestFullResourcePath.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/parser/TestFullResourcePath.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/parser/TestFullResourcePath.java
index 5a03676..fc9a0b8 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/parser/TestFullResourcePath.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/parser/TestFullResourcePath.java
@@ -53,13 +53,9 @@ public class TestFullResourcePath {
   private static final OData oData = OData.newInstance();
   private static final Edm edm = oData.createServiceMetadata(
       new EdmTechProvider(), Collections.<EdmxReference> emptyList()).getEdm();
-  private final TestUriValidator testUri;
-  private final FilterValidator testFilter;
 
-  public TestFullResourcePath() {
-    testUri = new TestUriValidator().setEdm(edm);
-    testFilter = new FilterValidator().setEdm(edm);
-  }
+  private final TestUriValidator testUri = new TestUriValidator().setEdm(edm);
+  private final FilterValidator testFilter = new FilterValidator().setEdm(edm);
 
   @Test
   public void enumAndTypeDefAsKey() throws Exception {
@@ -1229,7 +1225,6 @@ public class TestFullResourcePath {
         .isType(EntityTypeProvider.nameETTwoPrim, false)
         .isTypeFilterOnCollection(EntityTypeProvider.nameETTwoBase)
         .isKeyPredicate(0, "PropertyInt16", "-32768");
-
   }
 
   @Test
@@ -2062,15 +2057,6 @@ public class TestFullResourcePath {
   }
 
   @Test
-  public void runFunctionImpEsAlias() throws Exception {
-
-    testUri.run("FICRTCollESTwoKeyNavParam(ParameterInt16=@parameterAlias)", "@parameterAlias=1");
-    testUri.run("FICRTCollESTwoKeyNavParam(ParameterInt16=@parameterAlias)/$count", "@parameterAlias=1");
-    testUri.runEx("FICRTCollESTwoKeyNavParam(ParameterInt16=@invalidAlias)", "@validAlias=1")
-        .isExValidation(UriValidationException.MessageKeys.MISSING_PARAMETER);
-  }
-
-  @Test
   public void runFunctionImpEsCast() throws Exception {
 
     testUri.run("FICRTCollESTwoKeyNavParam(ParameterInt16=1)/olingo.odata.test1.ETBaseTwoKeyNav")
@@ -2650,6 +2636,13 @@ public class TestFullResourcePath {
         .n()
         .isNavProperty("NavPropertyETTwoKeyNavOne", EntityTypeProvider.nameETTwoKeyNav, false);
 
+    testUri.run("ESTwoKeyNav", "$expand=olingo.odata.test1.ETBaseTwoKeyNav/PropertyCompNav/*")
+        .isKind(UriInfoKind.resource).goPath().first()
+        .goExpand().first()
+        .isExpandStartType(EntityTypeProvider.nameETBaseTwoKeyNav)
+        .isSegmentStar()
+        .goPath().last().isComplexProperty("PropertyCompNav", ComplexTypeProvider.nameCTBasePrimCompNav, false);
+
     testUri.run("ESTwoKeyNav", "$expand=olingo.odata.test1.ETBaseTwoKeyNav/PropertyCompNav"
         + "/olingo.odata.test1.CTTwoBasePrimCompNav/NavPropertyETTwoKeyNavOne")
         .isKind(UriInfoKind.resource).goPath().first()
@@ -2736,6 +2729,8 @@ public class TestFullResourcePath {
         .isExSemantic(MessageKeys.EXPRESSION_PROPERTY_NOT_IN_TYPE);
     testUri.runEx("ESTwoKeyNav", "$expand=PropertyCompNav/undefined")
         .isExSemantic(MessageKeys.EXPRESSION_PROPERTY_NOT_IN_TYPE);
+    testUri.runEx("ESTwoKeyNav", "$expand=PropertyCompNav/*+")
+        .isExSyntax(UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION);
   }
 
   @Test
@@ -2874,6 +2869,7 @@ public class TestFullResourcePath {
         .isExSyntax(UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION);
     testUri.runEx("ESTwoKeyNav", "$select=olingo.odata.test1.1")
         .isExSemantic(MessageKeys.UNKNOWN_PART);
+    testUri.runEx("ESTwoKeyNav", "$select=unknown_namespace.*").isExSemantic(MessageKeys.UNKNOWN_PART);
     testUri.runEx("ESTwoKeyNav", "$select=olingo.odata.test1.ETKeyNav")
         .isExSemantic(MessageKeys.INCOMPATIBLE_TYPE_FILTER);
     testUri.runEx("ESTwoKeyNav", "$select=PropertyCompNav/olingo.odata.test1.CTTwoPrim")
@@ -3771,7 +3767,8 @@ public class TestFullResourcePath {
   @Test
   public void filterFunctions() throws Exception {
     testFilter.runOnETAllPrim(
-        "olingo.odata.test1.UFCRTETTwoKeyNavParamCTTwoPrim(ParameterCTTwoPrim=@ParamAlias) eq null")
+        "olingo.odata.test1.UFCRTETTwoKeyNavParamCTTwoPrim(ParameterCTTwoPrim=@ParamAlias) eq null"
+        + "&@ParamAlias={}")
         .is("<<UFCRTETTwoKeyNavParamCTTwoPrim> eq <null>>")
         .left().goPath()
         .first()
@@ -3803,14 +3800,14 @@ public class TestFullResourcePath {
         .n().isPrimitiveProperty("PropertyString", PropertyProvider.nameString, false);
 
     testFilter.runOnETTwoKeyNav("PropertyComp/olingo.odata.test1.BFCCTPrimCompRTETTwoKeyNavParam"
-        + "(ParameterString=null)/PropertyString eq 'SomeString'")
+        + "(ParameterString='1')/PropertyString eq 'SomeString'")
         .is("<<PropertyComp/BFCCTPrimCompRTETTwoKeyNavParam/PropertyString> eq <'SomeString'>>")
         .root().left().goPath()
         .first()
         .isComplexProperty("PropertyComp", ComplexTypeProvider.nameCTPrimComp, false)
         .n()
         .isFunction("BFCCTPrimCompRTETTwoKeyNavParam")
-        .isParameter(0, "ParameterString", null)
+        .isParameter(0, "ParameterString", "'1'")
         .n()
         .isPrimitiveProperty("PropertyString", PropertyProvider.nameString, false);
 
@@ -3880,7 +3877,8 @@ public class TestFullResourcePath {
         .isPrimitiveProperty("PropertyInt16", PropertyProvider.nameInt16, false);
 
     testFilter.runOnETTwoKeyNav("olingo.odata.test1.UFCRTETTwoKeyNavParam(ParameterInt16=@Param1Alias)"
-        + "/PropertyInt16 eq 2")
+        + "/PropertyInt16 eq 2"
+        + "&@Param1Alias=1")
         .root().left().goPath()
         .first()
         .isFunction("UFCRTETTwoKeyNavParam")
@@ -3912,6 +3910,9 @@ public class TestFullResourcePath {
         .n().isComplexProperty("PropertyComp", ComplexTypeProvider.nameCTPrimComp, false)
         .n().isComplexProperty("PropertyComp", ComplexTypeProvider.nameCTAllPrim, false)
         .n().isPrimitiveProperty("PropertyString", PropertyProvider.nameString, false);
+
+    testFilter.runOnETTwoKeyNavEx("olingo.odata.test1.UFCRTETTwoKeyNavParam(ParameterInt16=@alias)")
+        .isExValidation(UriValidationException.MessageKeys.MISSING_ALIAS);
   }
 
   @Test
@@ -4629,12 +4630,12 @@ public class TestFullResourcePath {
         .goParameter(1).isTypedLiteral(EntityTypeProvider.nameETKeyPrimNav);
 
     testFilter.runOnETAllPrim(
-        "olingo.odata.test1.UFCRTCTTwoPrimTwoParam(ParameterInt16=null,ParameterString=null) ne null")
+        "olingo.odata.test1.UFCRTCTTwoPrimTwoParam(ParameterInt16=1,ParameterString='1') ne null")
         .left()
         .goPath()
         .isFunction("UFCRTCTTwoPrimTwoParam")
-        .isParameter(0, "ParameterInt16", null)
-        .isParameter(1, "ParameterString", null);
+        .isParameter(0, "ParameterInt16", "1")
+        .isParameter(1, "ParameterString", "'1'");
 
     testFilter.runOnETKeyNavEx("cast(NavPropertyETKeyPrimNavOne,olingo.odata.test1.ETKeyNav)")
         .isExSemantic(MessageKeys.EXPRESSION_PROPERTY_NOT_IN_TYPE);
@@ -5023,21 +5024,24 @@ public class TestFullResourcePath {
         .n().isPrimitiveProperty("PropertyDate", PropertyProvider.nameDate, false);
 
     testFilter.runOrderByOnETTwoKeyNav("olingo.odata.test1.UFCRTETAllPrimTwoParam("
-        + "ParameterString=@ParamStringAlias,ParameterInt16=@ParamInt16Alias)/PropertyString eq 'SomeString'")
+        + "ParameterString=@ParamStringAlias,ParameterInt16=@ParamInt16Alias)/PropertyString eq 'SomeString'"
+        + "&@ParamStringAlias='1'&@ParamInt16Alias=1")
         .isSortOrder(0, false)
         .goOrder(0).isBinary(BinaryOperatorKind.EQ).left().goPath()
         .first().isFunction("UFCRTETAllPrimTwoParam").goUpFilterValidator()
         .goOrder(0).right().isLiteral("'SomeString'");
 
     testFilter.runOrderByOnETTwoKeyNav("olingo.odata.test1.UFCRTETAllPrimTwoParam("
-        + "ParameterString=@ParamStringAlias,ParameterInt16=@ParamInt16Alias)/PropertyString eq 'SomeString' asc")
+        + "ParameterString=@ParamStringAlias,ParameterInt16=@ParamInt16Alias)/PropertyString eq 'SomeString' asc"
+        + "&@ParamStringAlias='1'&@ParamInt16Alias=1")
         .isSortOrder(0, false)
         .goOrder(0).isBinary(BinaryOperatorKind.EQ).left().goPath()
         .first().isFunction("UFCRTETAllPrimTwoParam").goUpFilterValidator()
         .goOrder(0).right().isLiteral("'SomeString'");
 
     testFilter.runOrderByOnETTwoKeyNav("olingo.odata.test1.UFCRTETAllPrimTwoParam("
-        + "ParameterString=@ParamStringAlias,ParameterInt16=@ParamInt16Alias)/PropertyString eq 'SomeString' desc")
+        + "ParameterString=@ParamStringAlias,ParameterInt16=@ParamInt16Alias)/PropertyString eq 'SomeString' desc"
+        + "&@ParamStringAlias='1'&@ParamInt16Alias=1")
         .isSortOrder(0, true)
         .goOrder(0).isBinary(BinaryOperatorKind.EQ).left().goPath()
         .first().isFunction("UFCRTETAllPrimTwoParam").goUpFilterValidator()
@@ -5045,7 +5049,8 @@ public class TestFullResourcePath {
 
     testFilter.runOrderByOnETTwoKeyNav("olingo.odata.test1.UFCRTETAllPrimTwoParam("
         + "ParameterString=@ParamStringAlias,ParameterInt16=@ParamInt16Alias)/PropertyString eq 'SomeString' desc,"
-        + "PropertyString eq '1'")
+        + "PropertyString eq '1'"
+        + "&@ParamStringAlias='1'&@ParamInt16Alias=1")
         .isSortOrder(0, true)
         .goOrder(0).isBinary(BinaryOperatorKind.EQ).left().goPath()
         .first().isFunction("UFCRTETAllPrimTwoParam").goUpFilterValidator()
@@ -5553,14 +5558,6 @@ public class TestFullResourcePath {
   }
 
   @Test
-  public void alias() throws Exception {
-    testUri.run("ESTwoKeyNav(PropertyInt16=1,PropertyString=@A)", "@A='2'").goPath()
-        .isKeyPredicate(0, "PropertyInt16", "1")
-        .isKeyPredicateAlias(1, "PropertyString", "@A")
-        .isInAliasToValueMap("@A", "'2'");
-  }
-
-  @Test
   public void doublePercentDecoding() throws Exception {
     testUri.runEx("ESAllPrim%252832767%29").isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX);
   }
@@ -5775,13 +5772,42 @@ public class TestFullResourcePath {
   }
 
   @Test
-  public void parameterAliasLiteralValidation() throws Exception {
-    testUri.run("ESAllPrim(PropertyInt16=@p1)", "@p1=1");
-    testUri.run("ESAllPrim(PropertyInt16=@p1)", "@p1=-2");
-    testUri.runEx("ESAllPrim(PropertyInt16=@p1)", "@p1='ewe'")
-        .isExValidation(UriValidationException.MessageKeys.INVALID_KEY_PROPERTY);
+  public void alias() throws Exception {
+    testUri.run("ESTwoKeyNav(PropertyInt16=1,PropertyString=@A)", "@A='2'").goPath()
+        .isKeyPredicate(0, "PropertyInt16", "1")
+        .isKeyPredicateAlias(1, "PropertyString", "@A")
+        .isInAliasToValueMap("@A", "'2'");
+    testUri.run("ESAllPrim(PropertyInt16=@p1)", "@p1=1").goPath()
+        .isKeyPredicateAlias(0, "PropertyInt16", "@p1")
+        .isInAliasToValueMap("@p1", "1");
+    testUri.run("ESAllPrim(@p1)", "@p1=-2").goPath()
+        .isKeyPredicateAlias(0, "PropertyInt16", "@p1")
+        .isInAliasToValueMap("@p1", "-2");
+
+    testFilter.runOnETAllPrim("PropertyInt16 gt @alias&@alias=1")
+        .right().isAlias("@alias");
+    testFilter.runOnETAllPrim("@alias&@alias=@otherAlias&@otherAlias=true")
+        .isAlias("@alias");
+
+    testUri.runEx("ESAllPrim(@p1)")
+        .isExValidation(UriValidationException.MessageKeys.MISSING_ALIAS);
+    testUri.runEx("ESAllPrim(PropertyInt16=@p1)", "@p1='ewe'").isExSemantic(MessageKeys.UNKNOWN_PART);
     testUri.runEx("ESAllPrim(PropertyInt16=@p1)", "@p1='ewe")
         .isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX);
+    testFilter.runOnETKeyNavEx("PropertyInt16 gt @alias")
+        .isExValidation(UriValidationException.MessageKeys.MISSING_ALIAS);
+    testFilter.runOnETKeyNavEx("PropertyInt16 gt @alias&@alias=@alias")
+        .isExValidation(UriValidationException.MessageKeys.MISSING_ALIAS);
+    testFilter.runOnETKeyNavEx("@alias&@alias=@alias2&@alias2=true or @alias")
+        .isExValidation(UriValidationException.MessageKeys.MISSING_ALIAS);
+  }
+
+  @Test
+  public void functionImportParameterAlias() throws Exception {
+    testUri.run("FICRTCollESTwoKeyNavParam(ParameterInt16=@parameterAlias)", "@parameterAlias=1");
+    testUri.run("FICRTCollESTwoKeyNavParam(ParameterInt16=@parameterAlias)/$count", "@parameterAlias=1");
+    testUri.runEx("FICRTCollESTwoKeyNavParam(ParameterInt16=@invalidAlias)", "@validAlias=1")
+        .isExValidation(UriValidationException.MessageKeys.MISSING_ALIAS);
   }
 
   @Test
@@ -5854,10 +5880,10 @@ public class TestFullResourcePath {
         .isExValidation(UriValidationException.MessageKeys.MISSING_PARAMETER);
 
     testUri.runEx("FICRTCTTwoPrimTwoParam(ParameterInt16=1,ParameterString=@test)")
-        .isExValidation(UriValidationException.MessageKeys.MISSING_PARAMETER);
+        .isExValidation(UriValidationException.MessageKeys.MISSING_ALIAS);
 
     testUri.runEx("FICRTCTTwoPrimTwoParam(ParameterInt16=1,ParameterString=@test)", "@test=null")
-        .isExValidation(UriValidationException.MessageKeys.MISSING_PARAMETER);
+        .isExValidation(UriValidationException.MessageKeys.MISSING_ALIAS);
 
     testUri.run("FICRTCTTwoPrimTwoParam(ParameterInt16=1,ParameterString=@test)", "@test='null'");
 
@@ -5881,7 +5907,7 @@ public class TestFullResourcePath {
 
     testUri.runEx("ESTwoKeyNav", "$filter=olingo.odata.test1.BFCESTwoKeyNavRTStringParam"
         + "(ParameterComp=@p1) eq '0'&@p1={\"PropertyInt16\":1,\"PropertyString\":\"1\"}}")
-        .isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX);
+        .isExSemantic(MessageKeys.UNKNOWN_PART);
 
     testUri.runEx("ESTwoKeyNav", "$filter=olingo.odata.test1.BFCESTwoKeyNavRTStringParam"
         + "(ParameterComp=@p1) eq '0'&@p1={\"PropertyInt16\":[1,2,3]],\"PropertyString\":\"1\"}")

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/110c7b0e/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/queryoption/QueryOptionTest.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/queryoption/QueryOptionTest.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/queryoption/QueryOptionTest.java
index c3d90c9..4643283 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/queryoption/QueryOptionTest.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/queryoption/QueryOptionTest.java
@@ -132,7 +132,7 @@ public class QueryOptionTest {
     FilterOptionImpl option = new FilterOptionImpl();
     assertEquals(SystemQueryOptionKind.FILTER, option.getKind());
 
-    AliasImpl expression = new AliasImpl(null);
+    AliasImpl expression = new AliasImpl(null, null);
 
     option.setExpression(expression);
     assertEquals(expression, option.getExpression());
@@ -184,7 +184,7 @@ public class QueryOptionTest {
   public void testOrderByItemImpl() {
     OrderByItemImpl option = new OrderByItemImpl();
 
-    AliasImpl expression = new AliasImpl(null);
+    AliasImpl expression = new AliasImpl(null, null);
     option.setExpression(expression);
     assertEquals(expression, option.getExpression());
 

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/110c7b0e/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/queryoption/expression/ExpressionTest.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/queryoption/expression/ExpressionTest.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/queryoption/expression/ExpressionTest.java
index fad718b..66528a0 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/queryoption/expression/ExpressionTest.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/queryoption/expression/ExpressionTest.java
@@ -70,12 +70,12 @@ public class ExpressionTest {
 
   @Test
   public void aliasExpression() throws Exception {
-    AliasImpl expression = new AliasImpl("Test");
+    AliasImpl expression = new AliasImpl("@Test", null);
 
-    assertEquals("Test", expression.getParameterName());
+    assertEquals("@Test", expression.getParameterName());
 
     String output = expression.accept(new FilterTreeToText());
-    assertEquals("<Test>", output);
+    assertEquals("<@Test>", output);
   }
 
   @Test

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/110c7b0e/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/FilterValidator.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/FilterValidator.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/FilterValidator.java
index 161299c..600a2bd 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/FilterValidator.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/FilterValidator.java
@@ -36,6 +36,7 @@ import org.apache.olingo.server.api.uri.UriInfoKind;
 import org.apache.olingo.server.api.uri.UriResource;
 import org.apache.olingo.server.api.uri.queryoption.FilterOption;
 import org.apache.olingo.server.api.uri.queryoption.OrderByOption;
+import org.apache.olingo.server.api.uri.queryoption.expression.Alias;
 import org.apache.olingo.server.api.uri.queryoption.expression.Binary;
 import org.apache.olingo.server.api.uri.queryoption.expression.BinaryOperatorKind;
 import org.apache.olingo.server.api.uri.queryoption.expression.Enumeration;
@@ -102,11 +103,6 @@ public class FilterValidator implements TestValidator {
     return this;
   }
 
-  public FilterValidator setOrderBy(final OrderByOption orderBy) {
-    this.orderBy = orderBy;
-    return this;
-  }
-
   public FilterValidator setExpression(final Expression expression) {
     rootExpression = curExpression = expression;
     return this;
@@ -189,10 +185,7 @@ public class FilterValidator implements TestValidator {
 
   public FilterValidator runUri(final String path, final String query)
       throws UriParserException, UriValidationException {
-    Parser parser = new Parser(edm, odata);
-    UriInfo uriInfo = null;
-
-    uriInfo = parser.parseUri(path, query, null);
+    final UriInfo uriInfo = new Parser(edm, odata).parseUri(path, query, null);
 
     if (uriInfo.getKind() != UriInfoKind.resource) {
       fail("Filtervalidator can only be used on resourcePaths");
@@ -224,7 +217,7 @@ public class FilterValidator implements TestValidator {
       fail("Filtervalidator can only be used on resourcePaths");
     }
 
-    setOrderBy(uriInfo.getOrderByOption());
+    orderBy = uriInfo.getOrderByOption();
     return this;
   }
 
@@ -323,6 +316,11 @@ public class FilterValidator implements TestValidator {
     return this;
   }
 
+  public FilterValidator root() {
+    curExpression = filter == null ? rootExpression : filter.getExpression();
+    return this;
+  }
+
   public FilterValidator left() {
     if (!(curExpression instanceof Binary)) {
       fail("Current expression not a binary operator");
@@ -332,11 +330,6 @@ public class FilterValidator implements TestValidator {
     return this;
   }
 
-  public FilterValidator root() {
-    curExpression = filter == null ? rootExpression : filter.getExpression();
-    return this;
-  }
-
   public FilterValidator right() {
     if (!(curExpression instanceof Binary)) {
       fail("Current expression is not a binary operator");
@@ -360,7 +353,7 @@ public class FilterValidator implements TestValidator {
     if (!(curExpression instanceof Literal)) {
       fail("Current expression is not a literal");
     }
-    
+
     final EdmType type = ((Literal) curExpression).getType();
     assertNotNull(type);
     assertEquals(edmType, type);
@@ -448,7 +441,7 @@ public class FilterValidator implements TestValidator {
     return this;
   }
 
-  public FilterValidator isEnum(final FullQualifiedName nameenstring, final List<String> enumValues) {
+  public FilterValidator isEnum(final FullQualifiedName name, final List<String> enumValues) {
     if (!(curExpression instanceof Enumeration)) {
       fail("Current expression not a enumeration");
     }
@@ -456,18 +449,24 @@ public class FilterValidator implements TestValidator {
     Enumeration enumeration = (Enumeration) curExpression;
 
     // check name
-    assertEquals(nameenstring, enumeration.getType().getFullQualifiedName());
+    assertEquals(name, enumeration.getType().getFullQualifiedName());
 
     // check values
-    int i = 0;
-    for (String item : enumValues) {
-      assertEquals(item, enumeration.getValues().get(i));
-      i++;
-    }
+    assertEquals(enumValues, enumeration.getValues());
 
     return this;
   }
 
+  public FilterValidator isAlias(final String name) {
+    if (curExpression instanceof Alias) {
+      final Alias alias = (Alias) curExpression;
+      assertEquals(name, alias.getParameterName());
+    } else {
+      fail("Current expression is not an alias.");
+    }
+    return this;
+  }
+
   public FilterValidator isSortOrder(final int index, final boolean descending) {
     assertEquals(descending, orderBy.getOrders().get(index).isDescending());
     return this;
@@ -489,4 +488,10 @@ public class FilterValidator implements TestValidator {
     assertEquals(messageKey, exception.getMessageKey());
     return this;
   }
+
+  public FilterValidator isExValidation(final UriValidationException.MessageKeys messageKey) {
+    assertEquals(UriValidationException.class, exception.getClass());
+    assertEquals(messageKey, exception.getMessageKey());
+    return this;
+  }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/110c7b0e/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/validator/UriValidatorTest.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/validator/UriValidatorTest.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/validator/UriValidatorTest.java
index 673b8ff..3d5e97f 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/validator/UriValidatorTest.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/validator/UriValidatorTest.java
@@ -30,7 +30,6 @@ import org.apache.olingo.server.api.edmx.EdmxReference;
 import org.apache.olingo.server.core.uri.parser.Parser;
 import org.apache.olingo.server.core.uri.parser.UriParserException;
 import org.apache.olingo.server.core.uri.parser.UriParserSemanticException;
-import org.apache.olingo.server.core.uri.parser.UriParserSyntaxException;
 import org.apache.olingo.server.core.uri.testutil.TestUriValidator;
 import org.apache.olingo.server.tecsvc.provider.EdmTechProvider;
 import org.junit.Test;
@@ -118,7 +117,7 @@ public class UriValidatorTest {
 
       { URI_REFERENCES, QO_FILTER }, { URI_REFERENCES, QO_FORMAT }, { URI_REFERENCES, QO_ORDERBY },
       { URI_REFERENCES, QO_SEARCH }, { URI_REFERENCES, QO_SKIP }, { URI_REFERENCES, QO_SKIPTOKEN },
-      { URI_REFERENCES, QO_TOP }, { URI_REFERENCES, QO_ID }, { URI_REFERENCES, QO_COUNT },
+      { URI_REFERENCES, QO_TOP }, { URI_REFERENCES, QO_COUNT },
 
       { URI_REFERENCE, QO_FORMAT },
 
@@ -204,7 +203,7 @@ public class UriValidatorTest {
       { URI_MEDIA_STREAM, QO_SEARCH }, { URI_MEDIA_STREAM, QO_SELECT }, { URI_MEDIA_STREAM, QO_SKIP },
       { URI_MEDIA_STREAM, QO_SKIPTOKEN }, { URI_MEDIA_STREAM, QO_TOP },
 
-      { URI_REFERENCES, QO_EXPAND }, { URI_REFERENCES, QO_SELECT },
+      { URI_REFERENCES, QO_ID }, { URI_REFERENCES, QO_EXPAND }, { URI_REFERENCES, QO_SELECT },
 
       { URI_REFERENCE, QO_FILTER }, { URI_REFERENCE, QO_ID }, { URI_REFERENCE, QO_EXPAND },
       { URI_REFERENCE, QO_COUNT }, { URI_REFERENCE, QO_ORDERBY }, { URI_REFERENCE, QO_SEARCH },
@@ -328,22 +327,18 @@ public class UriValidatorTest {
       new EdmTechProvider(), Collections.<EdmxReference> emptyList()).getEdm();
 
   @Test
-  public void serviceDocumentMustNotFailForHttpPostPutPatchDelete() throws Exception {
-    // We must not fail with a nullpointer here as the HTTP method to resource validation happens in the dispatcher
-    validate(URI_SERVICE, null, HttpMethod.GET);
-    validate(URI_SERVICE, null, HttpMethod.POST);
-    validate(URI_SERVICE, null, HttpMethod.PUT);
-    validate(URI_SERVICE, null, HttpMethod.DELETE);
-    validate(URI_SERVICE, null, HttpMethod.PATCH);
+  public void serviceDocumentMustNotFailForAllHttpMethods() throws Exception {
+    // We must not fail with a nullpointer here as the HTTP method to resource validation happens in the dispatcher.
+    for (final HttpMethod method : HttpMethod.values()) {
+      validate(URI_SERVICE, null, method);
+    }
   }
 
   @Test
   public void validateForHttpMethods() throws Exception {
-    validate(URI_ENTITY, null, HttpMethod.GET);
-    validate(URI_ENTITY, null, HttpMethod.POST);
-    validate(URI_ENTITY, null, HttpMethod.PUT);
-    validate(URI_ENTITY, null, HttpMethod.DELETE);
-    validate(URI_ENTITY, null, HttpMethod.PATCH);
+    for (final HttpMethod method : HttpMethod.values()) {
+      validate(URI_ENTITY, null, method);
+    }
   }
 
   @Test
@@ -378,45 +373,6 @@ public class UriValidatorTest {
   }
 
   @Test
-  public void validateSelect() throws Exception {
-    new TestUriValidator().setEdm(edm).run(URI_ENTITY, "$select=PropertyString");
-  }
-
-  @Test
-  public void validateOrderBy() throws Exception {
-    final TestUriValidator testUri = new TestUriValidator().setEdm(edm);
-
-    testUri.run(URI_ENTITY_SET, "$orderby=PropertyString");
-
-    testUri.runEx(URI_ENTITY, "$orderby=XXXX")
-        .isExSemantic(UriParserSemanticException.MessageKeys.EXPRESSION_PROPERTY_NOT_IN_TYPE);
-  }
-
-  @Test
-  public void validateCountInvalid() throws Exception {
-    new TestUriValidator().setEdm(edm).runEx(URI_ENTITY_SET, "$count=foo")
-        .isExSyntax(UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION);
-  }
-
-  @Test
-  public void validateTopInvalid() throws Exception {
-    new TestUriValidator().setEdm(edm).runEx(URI_ENTITY_SET, "$top=foo")
-        .isExSyntax(UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION);
-  }
-
-  @Test
-  public void validateSkipInvalid() throws Exception {
-    new TestUriValidator().setEdm(edm).runEx(URI_ENTITY_SET, "$skip=foo")
-        .isExSyntax(UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION);
-  }
-
-  @Test
-  public void validateDoubleSystemOptions() throws Exception {
-    new TestUriValidator().setEdm(edm).runEx(URI_ENTITY_SET, "$skip=1&$skip=2")
-        .isExSyntax(UriParserSyntaxException.MessageKeys.DOUBLE_SYSTEM_QUERY_OPTION);
-  }
-
-  @Test
   public void checkKeys() throws Exception {
     final TestUriValidator testUri = new TestUriValidator().setEdm(edm);
 
@@ -502,9 +458,9 @@ public class UriValidatorTest {
     try {
       new UriValidator().validate(new Parser(edm, odata).parseUri(path, query, null), method);
     } catch (final UriParserException e) {
-      fail("Failed for uri: " + path + '?' + query);
+      fail("Failed for " + method + " on URI: " + path + '?' + query);
     } catch (final UriValidationException e) {
-      fail("Failed for uri: " + path + '?' + query);
+      fail("Failed for " + method + " on URI: " + path + '?' + query);
     }
   }
 


[11/22] olingo-odata4 git commit: OLINGO-862: MediaEntity Type: HasStream is not inherited

Posted by mi...@apache.org.
OLINGO-862: MediaEntity Type: HasStream is not inherited

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


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

Branch: refs/heads/OLINGO-832_StreamSerializerPoC
Commit: 53065cdface25971ef50a7b97febf54c7e69c623
Parents: 5d7c128
Author: Frederik Zimmer <fr...@partake.de>
Authored: Tue Feb 2 12:29:49 2016 +0100
Committer: Christian Amend <ch...@sap.com>
Committed: Thu Feb 4 15:12:40 2016 +0100

----------------------------------------------------------------------
 .../commons/core/edm/EdmEntityTypeImpl.java      |  7 ++++++-
 .../core/edm/provider/EdmEntityTypeImplTest.java | 19 +++++++++++++++++++
 2 files changed, 25 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/53065cdf/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/EdmEntityTypeImpl.java
----------------------------------------------------------------------
diff --git a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/EdmEntityTypeImpl.java b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/EdmEntityTypeImpl.java
index 6d60afb..c532cb3 100644
--- a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/EdmEntityTypeImpl.java
+++ b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/EdmEntityTypeImpl.java
@@ -136,6 +136,11 @@ public class EdmEntityTypeImpl extends AbstractEdmStructuredType implements EdmE
 
   @Override
   public boolean hasStream() {
-    return hasStream;
+    checkBaseType();
+
+    if (hasStream || entityBaseType != null && entityBaseType.hasStream()) {
+      return true;
+    }
+    return false;
   }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/53065cdf/lib/commons-core/src/test/java/org/apache/olingo/server/core/edm/provider/EdmEntityTypeImplTest.java
----------------------------------------------------------------------
diff --git a/lib/commons-core/src/test/java/org/apache/olingo/server/core/edm/provider/EdmEntityTypeImplTest.java b/lib/commons-core/src/test/java/org/apache/olingo/server/core/edm/provider/EdmEntityTypeImplTest.java
index 6cbabff..d0013a2 100644
--- a/lib/commons-core/src/test/java/org/apache/olingo/server/core/edm/provider/EdmEntityTypeImplTest.java
+++ b/lib/commons-core/src/test/java/org/apache/olingo/server/core/edm/provider/EdmEntityTypeImplTest.java
@@ -241,6 +241,25 @@ public class EdmEntityTypeImplTest {
   }
 
   @Test
+  public void hasStreamInherited() throws Exception {
+    CsdlEdmProvider provider = mock(CsdlEdmProvider.class);
+    EdmProviderImpl edm = new EdmProviderImpl(provider);
+
+    FullQualifiedName baseName = new FullQualifiedName("namespace", "BaseTypeName");
+    CsdlEntityType baseType = new CsdlEntityType();
+    baseType.setHasStream(true);
+    when(provider.getEntityType(baseName)).thenReturn(baseType);
+
+    FullQualifiedName typeName = new FullQualifiedName("namespace", "typeName");
+    CsdlEntityType type = new CsdlEntityType();
+    type.setBaseType(baseName);
+    EdmEntityType typeWithBaseTypeWithStream = new EdmEntityTypeImpl(edm, typeName, type);
+    when(provider.getEntityType(typeName)).thenReturn(type);
+
+    assertTrue(typeWithBaseTypeWithStream.hasStream());
+  }
+
+  @Test
   public void complexKeyWithAlias() {
     List<String> keyPredicateNames = typeWithComplexKey.getKeyPredicateNames();
     assertEquals(2, keyPredicateNames.size());


[21/22] olingo-odata4 git commit: Merge branch 'OLINGO-864'

Posted by mi...@apache.org.
Merge branch 'OLINGO-864'


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

Branch: refs/heads/OLINGO-832_StreamSerializerPoC
Commit: 3c205f907e129fba303a283ff4f8ac9c094e768a
Parents: 187c229 7b26cc6
Author: Ramesh Reddy <ra...@jboss.org>
Authored: Fri Feb 12 09:23:09 2016 -0600
Committer: Ramesh Reddy <ra...@jboss.org>
Committed: Fri Feb 12 09:23:09 2016 -0600

----------------------------------------------------------------------
 .../client/AbstractParamTecSvcITCase.java       | 14 +++++
 .../commons/core/edm/primitivetype/EdmDate.java |  5 +-
 .../edm/primitivetype/EdmDateTimeOffset.java    | 62 ++++++++++++--------
 .../core/edm/primitivetype/EdmTimeOfDay.java    | 20 ++-----
 .../core/edm/primitivetype/EdmDateTest.java     |  1 -
 .../primitivetype/EdmDateTimeOffsetTest.java    |  9 ++-
 .../edm/primitivetype/EdmTimeOfDayTest.java     | 23 ++++++--
 .../olingo/server/tecsvc/data/DataCreator.java  | 10 +++-
 .../server/tecsvc/data/DataProviderTest.java    | 14 +++++
 .../json/ODataJsonSerializerTest.java           | 13 ++++
 10 files changed, 116 insertions(+), 55 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/3c205f90/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataCreator.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/3c205f90/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializerTest.java
----------------------------------------------------------------------


[20/22] olingo-odata4 git commit: OLINGO-880: Enable MetadataParser to load core vocabularies based on a perference setting, these are loaded loaded from local classpath, instead of making a web call

Posted by mi...@apache.org.
OLINGO-880: Enable MetadataParser to load core vocabularies based on a perference setting, these are loaded loaded from local classpath, instead of making a web call


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

Branch: refs/heads/OLINGO-832_StreamSerializerPoC
Commit: 187c229b6022923a028e6fe5a29a430e06003ff7
Parents: 801899a
Author: Ramesh Reddy <ra...@jboss.org>
Authored: Fri Feb 12 09:16:00 2016 -0600
Committer: Ramesh Reddy <ra...@jboss.org>
Committed: Fri Feb 12 09:16:00 2016 -0600

----------------------------------------------------------------------
 .../olingo/server/core/MetadataParser.java      | 118 +++---
 .../olingo/server/core/ReferenceResolver.java   |   3 +-
 .../server/core/SchemaBasedEdmProvider.java     |  39 +-
 .../resources/Org.OData.Capabilities.V1.xml     | 388 +++++++++++++++++++
 .../src/main/resources/Org.OData.Core.V1.xml    | 187 +++++++++
 .../main/resources/Org.OData.Measures.V1.xml    | 110 ++++++
 .../core/MetadataParserAnnotationsTest.java     |  11 +-
 .../olingo/server/core/MetadataParserTest.java  |   2 +-
 .../olingo/server/example/TripPinServlet.java   |   2 +
 .../src/test/resources/annotations.xml          |   2 +-
 10 files changed, 807 insertions(+), 55 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/187c229b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/MetadataParser.java
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/MetadataParser.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/MetadataParser.java
index b564792..03a6675 100644
--- a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/MetadataParser.java
+++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/MetadataParser.java
@@ -19,6 +19,7 @@
 package org.apache.olingo.server.core;
 
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.Reader;
 import java.net.MalformedURLException;
 import java.net.URI;
@@ -95,38 +96,68 @@ import org.apache.olingo.server.api.edmx.EdmxReferenceIncludeAnnotation;
  */
 public class MetadataParser {
   private boolean parseAnnotations = false;
-  private final String XML_LINK_NS = "http://www.w3.org/1999/xlink";
-  private ReferenceResolver referenceResolver = new DefaultReferenceResolver();
+  private static final String XML_LINK_NS = "http://www.w3.org/1999/xlink";
+  private ReferenceResolver defaultReferenceResolver = new DefaultReferenceResolver();
+  private boolean loadCoreVocabularies = false;
   
-  public void setParseAnnotations(boolean f) {
-    this.parseAnnotations = true;
+  public MetadataParser parseAnnotations(boolean parse) {
+    this.parseAnnotations = parse;
+    return this;
   }
   
-  public void setReferenceResolver(ReferenceResolver resolver) {
-    this.referenceResolver = resolver;
+  public MetadataParser referenceResolver(ReferenceResolver resolver) {
+    this.defaultReferenceResolver = resolver;
+    return this;
+  }
+  
+  public MetadataParser loadCoreVocabularies(boolean load) {
+    this.loadCoreVocabularies = load;
+    return this;
   }
   
   public ServiceMetadata buildServiceMetadata(Reader csdl) throws XMLStreamException {
+    SchemaBasedEdmProvider provider = buildEdmProvider(csdl,
+        this.defaultReferenceResolver, this.loadCoreVocabularies);
+    return new ServiceMetadataImpl(provider, provider.getReferences(), null);
+  }
+
+  public SchemaBasedEdmProvider buildEdmProvider(Reader csdl) throws XMLStreamException {
+    return buildEdmProvider(csdl, this.defaultReferenceResolver, this.loadCoreVocabularies);
+  }
+    
+  protected SchemaBasedEdmProvider buildEdmProvider(Reader csdl,
+      ReferenceResolver referenceResolver, boolean loadCoreVocabularies) throws XMLStreamException {
     XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
     XMLEventReader reader = xmlInputFactory.createXMLEventReader(csdl);
-
+    return buildEdmProvider(reader, referenceResolver, loadCoreVocabularies);
+  }
+  
+  protected SchemaBasedEdmProvider buildEdmProvider(InputStream csdl,
+      ReferenceResolver referenceResolver, boolean loadCoreVocabularies) throws XMLStreamException {
+    XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
+    XMLEventReader reader = xmlInputFactory.createXMLEventReader(csdl);
+    return buildEdmProvider(reader, referenceResolver, loadCoreVocabularies);
+  } 
+  
+  protected SchemaBasedEdmProvider buildEdmProvider(XMLEventReader reader,
+      ReferenceResolver referenceResolver, boolean loadCoreVocabularies) throws XMLStreamException {
     SchemaBasedEdmProvider provider = new SchemaBasedEdmProvider(referenceResolver);
-    final ArrayList<EdmxReference> references = new ArrayList<EdmxReference>();
-    
     new ElementReader<SchemaBasedEdmProvider>() {
       @Override
       void build(XMLEventReader reader, StartElement element, SchemaBasedEdmProvider provider,
           String name) throws XMLStreamException {
-        String version = attr(element, "Version");
         String xmlBase = attrNS(element, XML_LINK_NS, "base");
-        provider.setXMLBase(xmlBase);
+        provider.setXMLBase(xmlBase);        
+        String version = attr(element, "Version");
         if ("4.0".equals(version)) {
-          readDataServicesAndReference(reader, element, provider, references);
+          readDataServicesAndReference(reader, element, provider);
         } else {
           throw new XMLStreamException("Currently only V4 is supported.");
         }
       }
     }.read(reader, null, provider, "Edmx");
+    
+    // make sure there is nothing left to read, due to parser error
     if(reader.hasNext()) {
       XMLEvent event = reader.peek();
       throw new XMLStreamException(
@@ -135,34 +166,33 @@ public class MetadataParser {
                   event.asStartElement().getName().getLocalPart() : 
                   event.asEndElement().getName().getLocalPart()));
     }
-    provider.addReferences(references);
-    return new ServiceMetadataImpl(provider, references, null);
-  }
-
-  SchemaBasedEdmProvider buildEdmProvider(Reader csdl) throws XMLStreamException {
-    XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
-    XMLEventReader reader = xmlInputFactory.createXMLEventReader(csdl);
-    return buildEdmProvider(reader);
-  } 
+    
+    // load the core vocabularies
+    if (loadCoreVocabularies) {
+      loadVocabularySchema(provider, "Org.OData.Core.V1", "Org.OData.Core.V1.xml");
+      loadVocabularySchema(provider, "Org.OData.Capabilities.V1", "Org.OData.Capabilities.V1.xml");
+      loadVocabularySchema(provider, "Org.OData.Measures.V1", "Org.OData.Measures.V1.xml");
+    }    
+    return provider;
+  }  
   
-  SchemaBasedEdmProvider buildEdmProvider(XMLEventReader reader) throws XMLStreamException {
-    SchemaBasedEdmProvider provider = new SchemaBasedEdmProvider(this.referenceResolver);
-    new ElementReader<SchemaBasedEdmProvider>() {
-      @Override
-      void build(XMLEventReader reader, StartElement element, SchemaBasedEdmProvider provider,
-          String name) throws XMLStreamException {
-        String version = attr(element, "Version");
-        if ("4.0".equals(version)) {
-          readDataServicesAndReference(reader, element, provider, new ArrayList<EdmxReference>());
-        }
+  private void loadVocabularySchema(SchemaBasedEdmProvider provider, String namespace,
+      String resource) throws XMLStreamException {
+    CsdlSchema schema = provider.getSchema(namespace, false);
+    if (schema == null) {
+      InputStream is = this.getClass().getClassLoader().getResourceAsStream(resource);
+      if (is != null) {
+        SchemaBasedEdmProvider childProvider = buildEdmProvider(is, null, false);
+        provider.addSchema(childProvider.getSchema(namespace, false));
+      } else {
+        throw new XMLStreamException("failed to load "+resource+" core vocabulary");
       }
-    }.read(reader, null, provider, "Edmx");    
-    return provider;
+    }
   }  
   
   private void readDataServicesAndReference(XMLEventReader reader,
-      StartElement element, SchemaBasedEdmProvider provider,
-      final ArrayList<EdmxReference> references) throws XMLStreamException {
+      StartElement element, SchemaBasedEdmProvider provider) throws XMLStreamException {
+    final ArrayList<EdmxReference> references = new ArrayList<EdmxReference>();
     new ElementReader<SchemaBasedEdmProvider>() {
       @Override
       void build(XMLEventReader reader, StartElement element, SchemaBasedEdmProvider provider,
@@ -174,6 +204,7 @@ public class MetadataParser {
         }
       }
     }.read(reader, element, provider, "DataServices", "Reference");
+    provider.addReferences(references);
   }
 
   private void readReference(XMLEventReader reader, StartElement element,
@@ -782,7 +813,7 @@ public class MetadataParser {
     return property;
   }
 
-  private String attr(StartElement element, String name) {
+  private static String attr(StartElement element, String name) {
     Attribute attr = element.getAttributeByName(new QName(name));
     if (attr != null) {
       return attr.getValue();
@@ -790,7 +821,7 @@ public class MetadataParser {
     return null;
   }
 
-  private String attrNS(StartElement element, String ns, String name) {
+  private static String attrNS(StartElement element, String ns, String name) {
     Attribute attr = element.getAttributeByName(new QName(ns, name));
     if (attr != null) {
       return attr.getValue();
@@ -1043,9 +1074,9 @@ public class MetadataParser {
         throws XMLStreamException;
   }
   
-  class DefaultReferenceResolver implements ReferenceResolver{
+  private static class DefaultReferenceResolver implements ReferenceResolver {
     @Override
-    public SchemaBasedEdmProvider resolveReference(URI referenceUri, String xmlBase) {
+    public InputStream resolveReference(URI referenceUri, String xmlBase) {
       URL schemaURL = null;
       try {
         if (referenceUri.isAbsolute()) {
@@ -1057,17 +1088,12 @@ public class MetadataParser {
             throw new EdmException("No xml:base set to read the references from the metadata");
           }        
         }
-        
-        XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
-        XMLEventReader reader = xmlInputFactory.createXMLEventReader(schemaURL.openStream());
-        return buildEdmProvider(reader);
+        return schemaURL.openStream();
       } catch (MalformedURLException e) {
         throw new EdmException(e);
-      } catch (XMLStreamException e) {
-        throw new EdmException(e);
       } catch (IOException e) {
         throw new EdmException(e);
       }
     }
-  }
+  }   
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/187c229b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ReferenceResolver.java
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ReferenceResolver.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ReferenceResolver.java
index f7d5101..2ac79bc 100644
--- a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ReferenceResolver.java
+++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ReferenceResolver.java
@@ -18,6 +18,7 @@
  */
 package org.apache.olingo.server.core;
 
+import java.io.InputStream;
 import java.net.URI;
 
 public interface ReferenceResolver {
@@ -28,5 +29,5 @@ public interface ReferenceResolver {
    * @param xmlBase xml:base if provided by the metadata document; null otherwise
    * @return
    */
-  SchemaBasedEdmProvider resolveReference(URI referenceUri, String xmlBase);
+  InputStream resolveReference(URI referenceUri, String xmlBase);
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/187c229b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/SchemaBasedEdmProvider.java
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/SchemaBasedEdmProvider.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/SchemaBasedEdmProvider.java
index a2f23f6..a778e2c 100644
--- a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/SchemaBasedEdmProvider.java
+++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/SchemaBasedEdmProvider.java
@@ -18,11 +18,15 @@
  */
 package org.apache.olingo.server.core;
 
+import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 
+import javax.xml.stream.XMLStreamException;
+
+import org.apache.olingo.commons.api.edm.EdmException;
 import org.apache.olingo.commons.api.edm.FullQualifiedName;
 import org.apache.olingo.commons.api.edm.provider.CsdlAction;
 import org.apache.olingo.commons.api.edm.provider.CsdlActionImport;
@@ -60,14 +64,25 @@ public class SchemaBasedEdmProvider implements CsdlEdmProvider {
   void addSchema(CsdlSchema schema) {
     this.edmSchemas.add(schema);
   }
+  
+  List<EdmxReference> getReferences(){
+    return new ArrayList<EdmxReference>(references.values());
+  }
 
-  private CsdlSchema getSchema(String ns) {
+  CsdlSchema getSchema(String ns) {
+    return getSchema(ns, true);
+  }  
+  
+  CsdlSchema getSchema(String ns, boolean checkReferences) {
     for (CsdlSchema s : this.edmSchemas) {
       if (s.getNamespace().equals(ns)) {
         return s;
       }
     }
-    return getReferenceSchema(ns);
+    if (checkReferences) {
+      return getReferenceSchema(ns);
+    }
+    return null;
   }
 
   private CsdlSchema getReferenceSchema(String ns) {
@@ -77,7 +92,23 @@ public class SchemaBasedEdmProvider implements CsdlEdmProvider {
     if (this.referenceSchemas.get(ns) == null) {
       EdmxReference reference = this.references.get(ns);
       if (reference != null) {
-        SchemaBasedEdmProvider provider = this.referenceResolver.resolveReference(reference.getUri(), xmlBase);
+        SchemaBasedEdmProvider provider = null;
+        if (this.referenceResolver == null) {
+          throw new EdmException("Failed to load Reference "+reference.getUri());
+        } else {
+          InputStream is = this.referenceResolver.resolveReference(reference.getUri(), this.xmlBase);
+          if (is != null) {
+            try {
+              MetadataParser parser = new MetadataParser();
+              provider = parser.buildEdmProvider(is, this.referenceResolver, false);
+            } catch (XMLStreamException e) {
+              throw new EdmException("Failed to load Reference "+reference.getUri()+" parsing failed");
+            }
+          } else {
+            throw new EdmException("Failed to load Reference "+reference.getUri()+" loading failed");
+          }
+        }
+        // copy references
         for (EdmxReferenceInclude include : reference.getIncludes()) {
           this.referenceSchemas.put(include.getNamespace(), provider);
           if (include.getAlias() != null) {
@@ -381,5 +412,5 @@ public class SchemaBasedEdmProvider implements CsdlEdmProvider {
         this.xmlBase = base+"/";
       }
     }
-  }
+  } 
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/187c229b/lib/server-core-ext/src/main/resources/Org.OData.Capabilities.V1.xml
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/src/main/resources/Org.OData.Capabilities.V1.xml b/lib/server-core-ext/src/main/resources/Org.OData.Capabilities.V1.xml
new file mode 100644
index 0000000..991a0ae
--- /dev/null
+++ b/lib/server-core-ext/src/main/resources/Org.OData.Capabilities.V1.xml
@@ -0,0 +1,388 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+  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.
+
+-->
+<!--
+
+     OData Version 4.0 Plus Errata 02
+     OASIS Standard incorporating Approved Errata 02
+     30 October 2014
+     Copyright (c) OASIS Open 2014. All Rights Reserved.
+     Source: http://docs.oasis-open.org/odata/odata/v4.0/errata02/os/complete/vocabularies/
+ 
+-->
+<!--
+
+Technical Committee:
+  OASIS Open Data Protocol (OData) TC
+  https://www.oasis-open.org/committees/odata
+
+Chairs:
+  - Barbara Hartel (barbara.hartel@sap.com), SAP AG
+  - Ram Jeyaraman (Ram.Jeyaraman@microsoft.com), Microsoft
+
+Editors:
+  - Ralf Handl (ralf.handl@sap.com), SAP AG
+  - Michael Pizzo (mikep@microsoft.com), Microsoft
+  - Martin Zurmuehl (martin.zurmuehl@sap.com), SAP AG
+
+Additional artifacts: 
+  This CSDL document is one component of a Work Product which consists of:
+  - OData Version 4.0 Part 1: Protocol
+  - OData Version 4.0 Part 2: URL Conventions
+  - OData Version 4.0 Part 3: Common Schema Definition Language (CSDL)
+  - OData ABNF Construction Rules Version 4.0 
+  - OData ABNF Test Cases
+  - OData Core Vocabulary
+  - OData Capabilities Vocabulary (this document)
+  - OData Measures Vocabulary
+  - OData Metadata Service Entity Model
+  - OData EDMX XML Schema
+  - OData EDM XML Schema
+
+Related work:
+  This work product is related to the following two Work Products, each of 
+  which define alternate formats for OData payloads
+  - OData Atom Format Version 4.0
+  - OData JSON Format Version 4.0
+  This specification replaces or supersedes:
+  - None
+
+Declared XML namespaces:
+  - http://docs.oasis-open.org/odata/ns/edmx
+  - http://docs.oasis-open.org/odata/ns/edm
+
+Abstract:
+  The Open Data Protocol (OData) enables the creation of REST-based data
+  services, which allow resources, identified using Uniform Resource
+  Identifiers (URLs) and defined in a data model, to be published and 
+  edited by Web clients using simple HTTP messages. This document defines
+  the URL syntax for requests and the serialization format for primitive 
+  literals in request and response payloads.
+
+Overview:
+  This document contains terms describing capabilities of an OData service.  
+
+-->
+<edmx:Edmx xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx" Version="4.0">
+  <edmx:Reference Uri="http://docs.oasis-open.org/odata/odata/v4.0/os/vocabularies/Org.OData.Core.V1.xml">
+    <edmx:Include Alias="Core" Namespace="Org.OData.Core.V1" />
+  </edmx:Reference>
+  <edmx:DataServices>
+    <Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="Org.OData.Capabilities.V1" Alias="Capabilities">
+      <Annotation Term="Core.Description">
+        <String>
+          The Capabilities vocabulary aims to provide a way for service authors to describe
+          certain capabilities of an OData Service.
+        </String>
+      </Annotation>
+      <Annotation Term="Core.LongDescription">
+        <String>
+          There are some capabilities which are strongly recommended for services to support even
+          though they are optional. Support for $top and $skip is a good example as
+          supporting these query options helps with performance of a service and are essential. Such
+          capabilities are assumed to be default capabilities of an OData service even in
+          the case that a capabilities annotation doesn’t exist. Capabilities annotations are
+          mainly expected to be used to explicitly specify that a service doesn’t support such
+          capabilities. Capabilities annotations can as well be used to declaratively
+          specify the support of such capabilities.
+
+          On the other hand, there are some capabilities that a service may choose to support or
+          not support and in varying degrees. $filter and $orderby are such good examples.
+          This vocabulary aims to define terms to specify support or no support for such
+          capabilities.
+
+          A service is assumed to support by default the following capabilities even though an
+          annotation doesn’t exist:
+          - Countability ($count)
+          - Client pageability ($top, $skip)
+          - Expandability ($expand)
+          - Indexability by key
+          - Batch support ($batch)
+          - Navigability of navigation properties
+
+          A service is expected to support the following capabilities. If not supported, the
+          service is expected to call out the restrictions using annotations:
+          - Filterability ($filter)
+          - Sortability ($orderby)
+          - Queryability of top level entity sets
+          - Query functions
+
+          A client cannot assume that a service supports certain capabilities. A client can try, but
+          it needs to be prepared to handle an error in case the following capabilities are not
+          supported:
+          - Insertability
+          - Updatability
+          - Deletability
+        </String>
+      </Annotation>
+
+      <!-- Conformance Level -->
+
+      <Term Name="ConformanceLevel" Type="Capabilities.ConformanceLevelType" AppliesTo="EntityContainer" />
+      <EnumType Name="ConformanceLevelType">
+        <Member Name="Minimal" />
+        <Member Name="Intermediate" />
+        <Member Name="Advanced" />
+      </EnumType>
+
+      <!-- Request Capabilities -->
+
+      <Term Name="SupportedFormats" Type="Collection(Edm.String)">
+        <Annotation Term="Core.Description" String="Media types of supported formats, including format parameters" />
+        <Annotation Term="Core.IsMediaType" />
+      </Term>
+
+      <Term Name="AcceptableEncodings" Type="Collection(Edm.String)" AppliesTo="EntityContainer">
+        <Annotation Term="Core.Description" String="List of acceptable compression methods for ($batch) requests, e.g. gzip" />
+      </Term>
+
+      <!-- Supported Preferences -->
+
+      <Term Name="AsynchronousRequestsSupported" Type="Core.Tag" DefaultValue="true" AppliesTo="EntityContainer">
+        <Annotation Term="Core.Description" String="Service supports the asynchronous request preference" />
+      </Term>
+
+      <Term Name="BatchContinueOnErrorSupported" Type="Core.Tag" DefaultValue="true" AppliesTo="EntityContainer">
+        <Annotation Term="Core.Description" String="Service supports the continue on error preference" />
+      </Term>
+
+      <Term Name="IsolationSupported" Type="Capabilities.IsolationLevel" AppliesTo="EntityContainer">
+        <Annotation Term="Core.Description" String="Supported odata.isolation levels" />
+      </Term>
+      <EnumType Name="IsolationLevel" IsFlags="true">
+        <Member Name="Snapshot" Value="1" />
+      </EnumType>
+
+      <Term Name="CallbackSupported" Type="Capabilities.CallbackType" AppliesTo="EntityContainer EntitySet">
+        <Annotation Term="Core.Description" String="Supports callbacks for the specified protocols" />
+      </Term>
+      <Term Name="CrossJoinSupported" Type="Core.Tag" DefaultValue="true" AppliesTo="EntityContainer">
+        <Annotation Term="Core.Description" String="Supports cross joins for the entity sets in this container" />
+      </Term>
+      <ComplexType Name="CallbackType">
+        <Property Name="CallbackProtocols" Type="Collection(Capabilities.CallbackProtocol)" />
+        <Annotation Term="Core.Description"
+          String="A non-empty collection lists the full set of supported protocols. A empty collection means 'only HTTP is supported'" />
+      </ComplexType>
+      <ComplexType Name="CallbackProtocol">
+        <Property Name="Id" Type="Edm.String">
+          <Annotation Term="Core.Description" String="Protcol Identifier" />
+        </Property>
+        <Property Name="UrlTemplate" Type="Edm.String">
+          <Annotation Term="Core.Description"
+            String="URL Template including parameters. Parameters are enclosed in curly braces {} as defined in RFC6570" />
+        </Property>
+        <Property Name="DocumentationUrl" Type="Edm.String" Nullable="true">
+          <Annotation Term="Core.Description" String="Human readable description of the meaning of the URL Template parameters" />
+          <Annotation Term="Core.IsURL" />
+        </Property>
+      </ComplexType>
+
+      <Term Name="ChangeTracking" Type="Capabilities.ChangeTrackingType" AppliesTo="EntityContainer EntitySet">
+        <Annotation Term="Core.Description" String="Change tracking capabilities of this service or entity set" />
+      </Term>
+      <ComplexType Name="ChangeTrackingType">
+        <Property Name="Supported" Type="Edm.Boolean" DefaultValue="true">
+          <Annotation Term="Core.Description" String="This entity set supports the odata.track-changes preference" />
+        </Property>
+        <Property Name="FilterableProperties" Type="Collection(Edm.PropertyPath)">
+          <Annotation Term="Core.Description" String="Change tracking supports filters on these properties" />
+        </Property>
+        <Property Name="ExpandableProperties" Type="Collection(Edm.NavigationPropertyPath)">
+          <Annotation Term="Core.Description" String="Change tracking supports these properties expanded" />
+        </Property>
+      </ComplexType>
+
+      <!--Query Capabilities -->
+
+      <Term Name="CountRestrictions" Type="Capabilities.CountRestrictionsType" AppliesTo="EntitySet">
+        <Annotation Term="Core.Description" String="Restrictions on /$count path suffix and $count=true system query option" />
+      </Term>
+      <ComplexType Name="CountRestrictionsType">
+        <Property Name="Countable" Type="Edm.Boolean" DefaultValue="true">
+          <Annotation Term="Core.Description" String="Entities can be counted" />
+        </Property>
+        <Property Name="NonCountableProperties" Type="Collection(Edm.PropertyPath)">
+          <Annotation Term="Core.Description" String="These collection properties do not allow /$count segments" />
+        </Property>
+        <Property Name="NonCountableNavigationProperties" Type="Collection(Edm.NavigationPropertyPath)">
+          <Annotation Term="Core.Description" String="These navigation properties do not allow /$count segments" />
+        </Property>
+      </ComplexType>
+
+      <Term Name="NavigationRestrictions" Type="Capabilities.NavigationRestrictionsType" AppliesTo="EntitySet">
+        <Annotation Term="Core.Description" String="Restrictions on navigating properties according to OData URL conventions" />
+      </Term>
+      <ComplexType Name="NavigationRestrictionsType">
+        <Property Name="Navigability" Type="Capabilities.NavigationType">
+          <Annotation Term="Core.Description" String="Supported Navigability" />
+        </Property>
+        <Property Name="RestrictedProperties" Type="Collection(Capabilities.NavigationPropertyRestriction)" />
+      </ComplexType>
+      <ComplexType Name="NavigationPropertyRestriction">
+        <Property Name="NavigationProperty" Type="Edm.NavigationPropertyPath">
+          <Annotation Term="Core.Description" String="Navigation properties can be navigated" />
+        </Property>
+        <Property Name="Navigability" Type="Capabilities.NavigationType">
+          <Annotation Term="Core.Description" String="Navigation properties can be navigated to this level" />
+        </Property>
+      </ComplexType>
+      <EnumType Name="NavigationType">
+        <Member Name="Recursive">
+          <Annotation Term="Core.Description" String="Navigation properties can be recursively navigated" />
+        </Member>
+        <Member Name="Single">
+          <Annotation Term="Core.Description" String="Navigation properties can be navigated to a single level" />
+        </Member>
+        <Member Name="None">
+          <Annotation Term="Core.Description" String="Navigation properties are not navigable" />
+        </Member>
+      </EnumType>
+
+      <Term Name="IndexableByKey" Type="Core.Tag" DefaultValue="true" AppliesTo="EntitySet">
+        <Annotation Term="Core.Description" String="Supports key values according to OData URL conventions" />
+      </Term>
+
+      <Term Name="TopSupported" Type="Core.Tag" DefaultValue="true" AppliesTo="EntitySet">
+        <Annotation Term="Core.Description" String="Supports $top" />
+      </Term>
+      <Term Name="SkipSupported" Type="Core.Tag" DefaultValue="true" AppliesTo="EntitySet">
+        <Annotation Term="Core.Description" String="Supports $skip" />
+      </Term>
+
+      <Term Name="BatchSupported" Type="Core.Tag" DefaultValue="true" AppliesTo="EntityContainer">
+        <Annotation Term="Core.Description" String="Supports $batch requests" />
+      </Term>
+
+      <Term Name="FilterFunctions" Type="Collection(Edm.String)" AppliesTo="EntityContainer EntitySet">
+        <Annotation Term="Core.Description" String="List of functions supported in $filter" />
+      </Term>
+
+      <Term Name="FilterRestrictions" Type="Capabilities.FilterRestrictionsType" AppliesTo="EntitySet">
+        <Annotation Term="Core.Description" String="Restrictions on $filter expressions" />
+      </Term>
+      <ComplexType Name="FilterRestrictionsType">
+        <Property Name="Filterable" Type="Edm.Boolean" DefaultValue="true">
+          <Annotation Term="Core.Description" String="$filter is supported" />
+        </Property>
+        <Property Name="RequiresFilter" Type="Edm.Boolean" Nullable="true">
+          <Annotation Term="Core.Description" String="$filter is required" />
+        </Property>
+        <Property Name="RequiredProperties" Type="Collection(Edm.PropertyPath)">
+          <Annotation Term="Core.Description"
+            String="These properties must be specified in the $filter clause (properties of derived types are not allowed here)" />
+        </Property>
+        <Property Name="NonFilterableProperties" Type="Collection(Edm.PropertyPath)">
+          <Annotation Term="Core.Description" String="These properties cannot be used in $filter expressions" />
+        </Property>
+      </ComplexType>
+
+      <Term Name="SortRestrictions" Type="Capabilities.SortRestrictionsType" AppliesTo="EntitySet">
+        <Annotation Term="Core.Description" String="Restrictions on $orderby expressions" />
+      </Term>
+      <ComplexType Name="SortRestrictionsType">
+        <Property Name="Sortable" Type="Edm.Boolean" DefaultValue="true">
+          <Annotation Term="Core.Description" String="$orderby is supported" />
+        </Property>
+        <Property Name="AscendingOnlyProperties" Type="Collection(Edm.PropertyPath)">
+          <Annotation Term="Core.Description" String="These properties can only be used for sorting in Ascending order" />
+        </Property>
+        <Property Name="DescendingOnlyProperties" Type="Collection(Edm.PropertyPath)">
+          <Annotation Term="Core.Description" String="These properties can only be used for sorting in Descending order" />
+        </Property>
+        <Property Name="NonSortableProperties" Type="Collection(Edm.PropertyPath)">
+          <Annotation Term="Core.Description" String="These properties cannot be used in $orderby expressions" />
+        </Property>
+      </ComplexType>
+
+      <Term Name="ExpandRestrictions" Type="Capabilities.ExpandRestrictionsType" AppliesTo="EntitySet">
+        <Annotation Term="Core.Description" String="Restrictions on $expand expressions" />
+      </Term>
+      <ComplexType Name="ExpandRestrictionsType">
+        <Property Name="Expandable" Type="Edm.Boolean" DefaultValue="true">
+          <Annotation Term="Core.Description" String="$expand is supported" />
+        </Property>
+        <Property Name="NonExpandableProperties" Type="Collection(Edm.NavigationPropertyPath)">
+          <Annotation Term="Core.Description" String="These properties cannot be used in $expand expressions" />
+        </Property>
+      </ComplexType>
+
+      <Term Name="SearchRestrictions" Type="Capabilities.SearchRestrictionsType" AppliesTo="EntitySet">
+        <Annotation Term="Core.Description" String="Restrictions on $search expressions" />
+      </Term>
+      <ComplexType Name="SearchRestrictionsType">
+        <Property Name="Searchable" Type="Edm.Boolean" DefaultValue="true">
+          <Annotation Term="Core.Description" String="$search is supported" />
+        </Property>
+        <Property Name="UnsupportedExpressions" Type="Capabilities.SearchExpressions" DefaultValue="none">
+          <Annotation Term="Core.Description" String="Expressions supported in $search" />
+        </Property>
+      </ComplexType>
+      <EnumType Name="SearchExpressions" IsFlags="true">
+        <Member Name="none" Value="0" />
+        <Member Name="AND" Value="1" />
+        <Member Name="OR" Value="2" />
+        <Member Name="NOT" Value="4" />
+        <Member Name="phrase" Value="8" />
+        <Member Name="group" Value="16" />
+      </EnumType>
+
+      <!-- Data Modification Capabilities -->
+
+      <Term Name="InsertRestrictions" Type="Capabilities.InsertRestrictionsType" AppliesTo="EntitySet">
+        <Annotation Term="Core.Description" String="Restrictions on insert operations" />
+      </Term>
+      <ComplexType Name="InsertRestrictionsType">
+        <Property Name="Insertable" Type="Edm.Boolean" DefaultValue="true">
+          <Annotation Term="Core.Description" String="Entities can be inserted" />
+        </Property>
+        <Property Name="NonInsertableNavigationProperties" Type="Collection(Edm.NavigationPropertyPath)">
+          <Annotation Term="Core.Description" String="These navigation properties do not allow deep inserts" />
+        </Property>
+      </ComplexType>
+
+      <Term Name="UpdateRestrictions" Type="Capabilities.UpdateRestrictionsType" AppliesTo="EntitySet">
+        <Annotation Term="Core.Description" String="Restrictions on update operations" />
+      </Term>
+      <ComplexType Name="UpdateRestrictionsType">
+        <Property Name="Updatable" Type="Edm.Boolean" DefaultValue="true">
+          <Annotation Term="Core.Description" String="Entities can be updated" />
+        </Property>
+        <Property Name="NonUpdatableNavigationProperties" Type="Collection(Edm.NavigationPropertyPath)">
+          <Annotation Term="Core.Description" String="These navigation properties do not allow rebinding" />
+        </Property>
+      </ComplexType>
+
+      <Term Name="DeleteRestrictions" Type="Capabilities.DeleteRestrictionsType" AppliesTo="EntitySet">
+        <Annotation Term="Core.Description" String="Restrictions on delete operations" />
+      </Term>
+      <ComplexType Name="DeleteRestrictionsType">
+        <Property Name="Deletable" Type="Edm.Boolean" DefaultValue="true">
+          <Annotation Term="Core.Description" String="Entities can be deleted" />
+        </Property>
+        <Property Name="NonDeletableNavigationProperties" Type="Collection(Edm.NavigationPropertyPath)">
+          <Annotation Term="Core.Description" String="These navigation properties do not allow DeleteLink requests" />
+        </Property>
+      </ComplexType>
+
+    </Schema>
+  </edmx:DataServices>
+</edmx:Edmx>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/187c229b/lib/server-core-ext/src/main/resources/Org.OData.Core.V1.xml
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/src/main/resources/Org.OData.Core.V1.xml b/lib/server-core-ext/src/main/resources/Org.OData.Core.V1.xml
new file mode 100644
index 0000000..b9bb306
--- /dev/null
+++ b/lib/server-core-ext/src/main/resources/Org.OData.Core.V1.xml
@@ -0,0 +1,187 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+  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.
+
+-->
+<!--
+
+     OData Version 4.0 Plus Errata 02
+     OASIS Standard incorporating Approved Errata 02
+     30 October 2014
+     Copyright (c) OASIS Open 2014. All Rights Reserved.
+     Source: http://docs.oasis-open.org/odata/odata/v4.0/errata02/os/complete/vocabularies/
+ 
+-->
+<!--
+
+Technical Committee:
+  OASIS Open Data Protocol (OData) TC
+  https://www.oasis-open.org/committees/odata
+
+Chairs:
+  - Barbara Hartel (barbara.hartel@sap.com), SAP AG
+  - Ram Jeyaraman (Ram.Jeyaraman@microsoft.com), Microsoft
+
+Editors:
+  - Ralf Handl (ralf.handl@sap.com), SAP AG
+  - Michael Pizzo (mikep@microsoft.com), Microsoft
+  - Martin Zurmuehl (martin.zurmuehl@sap.com), SAP AG
+
+Additional artifacts: 
+  This CSDL document is one component of a Work Product which consists of:
+  - OData Version 4.0 Part 1: Protocol
+  - OData Version 4.0 Part 2: URL Conventions
+  - OData Version 4.0 Part 3: Common Schema Definition Language (CSDL)
+  - OData ABNF Construction Rules Version 4.0 
+  - OData ABNF Test Cases
+  - OData Core Vocabulary (this document)
+  - OData Capabilities Vocabulary
+  - OData Measures Vocabulary
+  - OData Metadata Service Entity Model
+  - OData EDMX XML Schema
+  - OData EDM XML Schema
+
+Related work:
+  This work product is related to the following two Work Products, each of 
+  which define alternate formats for OData payloads
+  - OData Atom Format Version 4.0
+  - OData JSON Format Version 4.0
+  This specification replaces or supersedes:
+  - None
+
+Declared XML namespaces:
+  - http://docs.oasis-open.org/odata/ns/edmx
+  - http://docs.oasis-open.org/odata/ns/edm
+
+Abstract:
+  The Open Data Protocol (OData) enables the creation of REST-based data
+  services, which allow resources, identified using Uniform Resource
+  Identifiers (URLs) and defined in a data model, to be published and 
+  edited by Web clients using simple HTTP messages. This document defines
+  the URL syntax for requests and the serialization format for primitive 
+  literals in request and response payloads.
+
+Overview:
+  This document contains Core terms needed to write vocabularies.  
+
+-->
+<edmx:Edmx xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx" Version="4.0">
+  <edmx:DataServices>
+    <Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="Org.OData.Core.V1" Alias="Core">
+      <Annotation Term="Core.Description">
+        <String>Core terms needed to write vocabularies</String>
+      </Annotation>
+
+      <!--Documentation -->
+
+      <Term Name="Description" Type="Edm.String">
+        <Annotation Term="Core.Description" String="A brief description of a model element" />
+        <Annotation Term="Core.IsLanguageDependent" />
+      </Term>
+
+      <Term Name="LongDescription" Type="Edm.String">
+        <Annotation Term="Core.Description" String="A lengthy description of a model element" />
+        <Annotation Term="Core.IsLanguageDependent" />
+      </Term>
+
+      <!-- Localization -->
+
+      <Term Name="IsLanguageDependent" Type="Core.Tag" DefaultValue="true" AppliesTo="Term Property">
+        <Annotation Term="Core.Description" String="Properties and terms annotated with this term are language-dependent" />
+        <Annotation Term="Core.RequiresType" String="Edm.String" />
+      </Term>
+
+      <!-- Term Restrictions -->
+
+      <TypeDefinition Name="Tag" UnderlyingType="Edm.Boolean">
+        <Annotation Term="Core.Description" String="This is the type to use for all tagging terms" />
+      </TypeDefinition>
+
+      <Term Name="RequiresType" Type="Edm.String" AppliesTo="Term">
+        <Annotation Term="Core.Description"
+          String="Terms annotated with this term can only be applied to elements that have a type that is identical to or derived from the given type name" />
+      </Term>
+
+      <!--Resource Paths -->
+
+      <Term Name="ResourcePath" Type="Edm.String" AppliesTo="EntitySet Singleton ActionImport FunctionImport">
+        <Annotation Term="Core.Description"
+          String="Resource path for entity container child, can be relative to xml:base and the request URL" />
+        <Annotation Term="Core.IsUrl" />
+      </Term>
+
+      <Term Name="DereferenceableIDs" Type="Core.Tag" DefaultValue="true" AppliesTo="EntityContainer">
+        <Annotation Term="Core.Description" String="Entity-ids are URLs that locate the identified entity" />
+      </Term>
+
+      <Term Name="ConventionalIDs" Type="Core.Tag" DefaultValue="true" AppliesTo="EntityContainer">
+        <Annotation Term="Core.Description" String="Entity-ids follow OData URL conventions" />
+      </Term>
+
+      <!-- Permissions -->
+
+      <Term Name="Permissions" Type="Core.Permission" AppliesTo="Property">
+        <Annotation Term="Core.Description" String="Permissions available for a property.The value of 2 is reserved for future use." />
+      </Term>
+      <EnumType Name="Permission" IsFlags="true">
+        <Member Name="None" Value="0" />
+        <Member Name="Read" Value="1" />
+        <Member Name="ReadWrite" Value="3" />
+      </EnumType>
+
+      <!-- Metadata Extensions -->
+
+      <Term Name="Immutable" Type="Core.Tag" DefaultValue="true" AppliesTo="Property">
+        <Annotation Term="Core.Description"
+          String="A value for this non-key property can be provided on insert and remains unchanged on update" />
+      </Term>
+
+      <Term Name="Computed" Type="Core.Tag" DefaultValue="true" AppliesTo="Property">
+        <Annotation Term="Core.Description" String="A value for this property is generated on both insert and update" />
+      </Term>
+
+      <Term Name="IsURL" Type="Core.Tag" DefaultValue="true" AppliesTo="Property Term">
+        <Annotation Term="Core.Description" String="Properties and terms annotated with this term MUST contain a valid URL" />
+        <Annotation Term="Core.RequiresType" String="Edm.String" />
+      </Term>
+
+      <Term Name="AcceptableMediaTypes" Type="Collection(Edm.String)" AppliesTo="EntityType Property">
+        <Annotation Term="Core.Description"
+          String="Lists the MIME types acceptable for the annotated entity type marked with HasStream=&quot;true&quot; or the annotated stream property" />
+        <Annotation Term="Core.IsMediaType" />
+      </Term>
+
+      <Term Name="MediaType" Type="Edm.String" AppliesTo="Property">
+        <Annotation Term="Core.IsMediaType" />
+        <Annotation Term="Core.RequiresType" String="Edm.Binary" />
+      </Term>
+
+      <Term Name="IsMediaType" Type="Core.Tag" DefaultValue="true" AppliesTo="Property Term">
+        <Annotation Term="Core.Description" String="Properties and terms annotated with this term MUST contain a valid MIME type" />
+        <Annotation Term="Core.RequiresType" String="Edm.String" />
+      </Term>
+
+      <Term Name="OptimisticConcurrency" Type="Collection(Edm.PropertyPath)" AppliesTo="EntitySet">
+        <Annotation Term="Core.Description"
+          String="Data modification requires the use of Etags. A non-empty collection contains the set of properties that are used to compute the ETag" />
+      </Term>
+
+    </Schema>
+  </edmx:DataServices>
+</edmx:Edmx>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/187c229b/lib/server-core-ext/src/main/resources/Org.OData.Measures.V1.xml
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/src/main/resources/Org.OData.Measures.V1.xml b/lib/server-core-ext/src/main/resources/Org.OData.Measures.V1.xml
new file mode 100644
index 0000000..39f3e40
--- /dev/null
+++ b/lib/server-core-ext/src/main/resources/Org.OData.Measures.V1.xml
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+  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.
+
+-->
+<!--
+
+     OData Version 4.0 Plus Errata 02
+     OASIS Standard incorporating Approved Errata 02
+     30 October 2014
+     Copyright (c) OASIS Open 2014. All Rights Reserved.
+     Source: http://docs.oasis-open.org/odata/odata/v4.0/errata02/os/complete/vocabularies/
+ 
+-->
+<!--
+
+Technical Committee:
+  OASIS Open Data Protocol (OData) TC
+  https://www.oasis-open.org/committees/odata
+
+Chairs:
+  - Barbara Hartel (barbara.hartel@sap.com), SAP AG
+  - Ram Jeyaraman (Ram.Jeyaraman@microsoft.com), Microsoft
+
+Editors:
+  - Ralf Handl (ralf.handl@sap.com), SAP AG
+  - Michael Pizzo (mikep@microsoft.com), Microsoft
+  - Martin Zurmuehl (martin.zurmuehl@sap.com), SAP AG
+
+Additional artifacts: 
+  This CSDL document is one component of a Work Product which consists of:
+  - OData Version 4.0 Part 1: Protocol
+  - OData Version 4.0 Part 2: URL Conventions
+  - OData Version 4.0 Part 3: Common Schema Definition Language (CSDL)
+  - OData ABNF Construction Rules Version 4.0 
+  - OData ABNF Test Cases
+  - OData Core Vocabulary
+  - OData Capabilities Vocabulary
+  - OData Measures Vocabulary (this document)
+  - OData Metadata Service Entity Model
+  - OData EDMX XML Schema
+  - OData EDM XML Schema
+
+Related work:
+  This work product is related to the following two Work Products, each of 
+  which define alternate formats for OData payloads
+  - OData Atom Format Version 4.0
+  - OData JSON Format Version 4.0
+  This specification replaces or supersedes:
+  - None
+
+Declared XML namespaces:
+  - http://docs.oasis-open.org/odata/ns/edmx
+  - http://docs.oasis-open.org/odata/ns/edm
+
+Abstract:
+  The Open Data Protocol (OData) enables the creation of REST-based data
+  services, which allow resources, identified using Uniform Resource
+  Identifiers (URLs) and defined in a data model, to be published and 
+  edited by Web clients using simple HTTP messages. This document defines
+  the URL syntax for requests and the serialization format for primitive 
+  literals in request and response payloads.
+
+Overview:
+  This document contains terms describing monetary amounts and measured quantities.  
+
+-->
+<edmx:Edmx xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx" Version="4.0">
+  <edmx:Reference Uri="http://docs.oasis-open.org/odata/odata/v4.0/os/vocabularies/Org.OData.Core.V1.xml">
+    <edmx:Include Alias="Core" Namespace="Org.OData.Core.V1" />
+  </edmx:Reference>
+  <edmx:DataServices>
+    <Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="Org.OData.Measures.V1" Alias="Measures">
+      <Annotation Term="Core.Description">
+        <String>Terms describing monetary amounts and measured quantities</String>
+      </Annotation>
+
+      <Term Name="ISOCurrency" Type="Edm.String" AppliesTo="Property">
+        <Annotation Term="Core.Description" String="The currency for this monetary amount as an ISO 4217 currency code" />
+      </Term>
+
+      <Term Name="Scale" Type="Edm.Byte" AppliesTo="Property">
+        <Annotation Term="Core.Description"
+          String="The number of significant decimal places in the scale part (less than or equal to the number declared in the Scale facet)" />
+        <Annotation Term="Core.RequiresType" String="Edm.Decimal" />
+      </Term>
+
+      <Term Name="Unit" Type="Edm.String" AppliesTo="Property">
+        <Annotation Term="Core.Description" String="The unit of measure for this measured quantity, e.g. cm for centimeters or % for percentages" />
+      </Term>
+
+    </Schema>
+  </edmx:DataServices>
+</edmx:Edmx>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/187c229b/lib/server-core-ext/src/test/java/org/apache/olingo/server/core/MetadataParserAnnotationsTest.java
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/src/test/java/org/apache/olingo/server/core/MetadataParserAnnotationsTest.java b/lib/server-core-ext/src/test/java/org/apache/olingo/server/core/MetadataParserAnnotationsTest.java
index 7912dc8..d71c54d 100644
--- a/lib/server-core-ext/src/test/java/org/apache/olingo/server/core/MetadataParserAnnotationsTest.java
+++ b/lib/server-core-ext/src/test/java/org/apache/olingo/server/core/MetadataParserAnnotationsTest.java
@@ -51,7 +51,7 @@ import org.junit.Before;
 import org.junit.Test;
 
 public class MetadataParserAnnotationsTest {
-  final String NS = "Org.OData.Core.V1";
+  final String NS = "Org.OData.AnnoatationTest";
   final FullQualifiedName NSF = new FullQualifiedName(NS);
 
   CsdlEdmProvider provider = null;
@@ -59,7 +59,8 @@ public class MetadataParserAnnotationsTest {
   @Before
   public void setUp() throws Exception {
     MetadataParser parser = new MetadataParser();
-    parser.setParseAnnotations(true);
+    parser.parseAnnotations(true);
+    parser.loadCoreVocabularies(true);
     provider = (CsdlEdmProvider) parser.buildEdmProvider(new FileReader("src/test/resources/annotations.xml"));
   }
 
@@ -204,5 +205,11 @@ public class MetadataParserAnnotationsTest {
   public void testTermAppliesTo() throws ODataException {
     CsdlTerm term = this.provider.getTerm(new FullQualifiedName(NS, "IsURI"));
     assertEquals(Arrays.asList("Property", "PropertyPath"), term.getAppliesTo());
+  }
+  
+  @Test
+  public void checkCoreVocabularies() throws ODataException {
+    CsdlTerm term = this.provider.getTerm(new FullQualifiedName("Org.OData.Core.V1", "Description"));
+    assertEquals("Edm.String", term.getType());
   }  
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/187c229b/lib/server-core-ext/src/test/java/org/apache/olingo/server/core/MetadataParserTest.java
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/src/test/java/org/apache/olingo/server/core/MetadataParserTest.java b/lib/server-core-ext/src/test/java/org/apache/olingo/server/core/MetadataParserTest.java
index 97f19b5..83160b4 100644
--- a/lib/server-core-ext/src/test/java/org/apache/olingo/server/core/MetadataParserTest.java
+++ b/lib/server-core-ext/src/test/java/org/apache/olingo/server/core/MetadataParserTest.java
@@ -54,7 +54,7 @@ public class MetadataParserTest {
   @Before
   public void setUp() throws Exception {
     MetadataParser parser = new MetadataParser();
-    parser.setParseAnnotations(true);
+    parser.parseAnnotations(true);
     provider = (CsdlEdmProvider) parser.buildEdmProvider(new FileReader("src/test/resources/trippin.xml"));
   }
 

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/187c229b/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinServlet.java
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinServlet.java b/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinServlet.java
index 036cd78..06e498c 100644
--- a/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinServlet.java
+++ b/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinServlet.java
@@ -50,6 +50,8 @@ public class TripPinServlet extends HttpServlet {
     ServiceMetadata metadata = null;
 
     try {
+      parser.parseAnnotations(true);
+      parser.loadCoreVocabularies(true);
       metadata = parser.buildServiceMetadata(new FileReader("src/test/resources/trippin.xml"));
     } catch (XMLStreamException e) {
       throw new IOException(e);

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/187c229b/lib/server-core-ext/src/test/resources/annotations.xml
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/src/test/resources/annotations.xml b/lib/server-core-ext/src/test/resources/annotations.xml
index fce46a8..1c5281a 100644
--- a/lib/server-core-ext/src/test/resources/annotations.xml
+++ b/lib/server-core-ext/src/test/resources/annotations.xml
@@ -13,7 +13,7 @@
 	Version="4.0">
 	<edmx:DataServices>
 		<Schema xmlns="http://docs.oasis-open.org/odata/ns/edm"
-			Namespace="Org.OData.Core.V1" Alias="Core">
+			Namespace="Org.OData.AnnoatationTest" Alias="test">
 
 			<Annotation Term="Core.Description">
 				<String>Core terms needed to write vocabularies</String>


[08/22] olingo-odata4 git commit: [OLINGO-852] less warnings + general clean-up

Posted by mi...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/fit/src/main/java/org/apache/olingo/fit/Services.java
----------------------------------------------------------------------
diff --git a/fit/src/main/java/org/apache/olingo/fit/Services.java b/fit/src/main/java/org/apache/olingo/fit/Services.java
index 45f11a5..698938e 100644
--- a/fit/src/main/java/org/apache/olingo/fit/Services.java
+++ b/fit/src/main/java/org/apache/olingo/fit/Services.java
@@ -25,15 +25,22 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStreamWriter;
 import java.net.URI;
+import java.util.AbstractMap;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.ConcurrentModificationException;
+import java.util.Enumeration;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.UUID;
+import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
+import javax.mail.Header;
 import javax.mail.internet.MimeBodyPart;
 import javax.mail.internet.MimeMultipart;
 import javax.ws.rs.BadRequestException;
@@ -51,6 +58,8 @@ import javax.ws.rs.Produces;
 import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.Context;
 import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedHashMap;
+import javax.ws.rs.core.MultivaluedMap;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.Response.Status;
 import javax.ws.rs.core.UriInfo;
@@ -59,63 +68,140 @@ import org.apache.commons.codec.binary.Base64;
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.math.NumberUtils;
+import org.apache.commons.lang3.tuple.Pair;
 import org.apache.cxf.interceptor.InInterceptors;
+import org.apache.cxf.jaxrs.client.WebClient;
 import org.apache.cxf.jaxrs.ext.multipart.Attachment;
 import org.apache.cxf.jaxrs.ext.multipart.Multipart;
 import org.apache.cxf.jaxrs.ext.multipart.MultipartBody;
 import org.apache.olingo.client.api.data.ResWrap;
+import org.apache.olingo.client.api.serialization.ODataDeserializer;
+import org.apache.olingo.client.api.serialization.ODataSerializer;
+import org.apache.olingo.client.core.serialization.AtomSerializer;
+import org.apache.olingo.client.core.serialization.JsonDeserializer;
+import org.apache.olingo.client.core.serialization.JsonSerializer;
+import org.apache.olingo.commons.api.data.ComplexValue;
 import org.apache.olingo.commons.api.data.Entity;
 import org.apache.olingo.commons.api.data.EntityCollection;
 import org.apache.olingo.commons.api.data.Link;
 import org.apache.olingo.commons.api.data.Property;
 import org.apache.olingo.commons.api.data.ValueType;
-import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion;
+import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
+import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
 import org.apache.olingo.commons.api.format.ContentType;
 import org.apache.olingo.commons.core.edm.EdmTypeInfo;
+import org.apache.olingo.commons.core.edm.primitivetype.EdmPrimitiveTypeFactory;
+import org.apache.olingo.fit.metadata.EntityType;
 import org.apache.olingo.fit.metadata.Metadata;
+import org.apache.olingo.fit.metadata.NavigationProperty;
 import org.apache.olingo.fit.methods.PATCH;
 import org.apache.olingo.fit.rest.ResolvingReferencesInterceptor;
 import org.apache.olingo.fit.rest.XHTTPMethodInterceptor;
+import org.apache.olingo.fit.serializer.FITAtomDeserializer;
 import org.apache.olingo.fit.utils.AbstractUtilities;
 import org.apache.olingo.fit.utils.Accept;
 import org.apache.olingo.fit.utils.Commons;
 import org.apache.olingo.fit.utils.ConstantKey;
 import org.apache.olingo.fit.utils.Constants;
 import org.apache.olingo.fit.utils.FSManager;
+import org.apache.olingo.fit.utils.JSONUtilities;
 import org.apache.olingo.fit.utils.LinkInfo;
+import org.apache.olingo.fit.utils.XMLUtilities;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Service;
 
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
 @Service
 @Path("/V40/Static.svc")
 @InInterceptors(classes = { XHTTPMethodInterceptor.class, ResolvingReferencesInterceptor.class })
-public class Services extends AbstractServices {
+public class Services {
 
   /**
-   * CR/LF.
+   * Logger.
    */
-  protected static final byte[] CRLF = { 13, 10 };
-
-  protected static final Pattern RELENTITY_SELECT_PATTERN = Pattern.compile("^.*\\(\\$select=.*\\)$");
+  protected static final Logger LOG = LoggerFactory.getLogger(Services.class);
 
-  protected static final Pattern CROSSJOIN_PATTERN = Pattern.compile(
+  private static final Pattern REQUEST_PATTERN = Pattern.compile("(.*) (http://.*) HTTP/.*");
+  private static final Pattern BATCH_REQUEST_REF_PATTERN = Pattern.compile("(.*) ([$]\\d+)(.*) HTTP/.*");
+  private static final Pattern REF_PATTERN = Pattern.compile("([$]\\d+)");
+  private static final Pattern RELENTITY_SELECT_PATTERN = Pattern.compile("^.*\\(\\$select=.*\\)$");
+  private static final Pattern CROSSJOIN_PATTERN = Pattern.compile(
       "^\\$crossjoin\\(.*\\)\\?\\$filter=\\([a-zA-Z/]+ eq [a-zA-Z/]+\\)$");
+  protected static final String BOUNDARY = "batch_243234_25424_ef_892u748";
+  protected static final String MULTIPART_MIXED = "multipart/mixed";
+  protected static final String APPLICATION_OCTET_STREAM = "application/octet-stream";
 
   private final Map<String, String> providedAsync = new HashMap<String, String>();
 
+  protected final ODataDeserializer atomDeserializer = new FITAtomDeserializer();
+  protected final ODataDeserializer jsonDeserializer = new JsonDeserializer(true);
+  protected final ODataSerializer atomSerializer = new AtomSerializer(true);
+  protected final ODataSerializer jsonSerializer = new JsonSerializer(true, ContentType.JSON_FULL_METADATA);
+
+  protected final Metadata metadata;
+  protected final XMLUtilities xml;
+  protected final JSONUtilities json;
+
   public Services() throws IOException {
-    super(ODataServiceVersion.V40, Commons.getMetadata(ODataServiceVersion.V40));
+    this(Commons.getMetadata());
   }
 
   protected Services(final Metadata metadata) throws IOException {
-    super(ODataServiceVersion.V40, metadata);
+    this.metadata = metadata;
+    xml = new XMLUtilities(metadata);
+    json = new JSONUtilities(metadata);
+  }
+
+  /**
+   * Provide sample services.
+   *
+   * @param accept Accept header.
+   * @return OData services.
+   */
+  @GET
+  public Response getServices(@HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept) {
+    try {
+      final Accept acceptType = Accept.parse(accept);
+
+      if (acceptType == Accept.ATOM) {
+        throw new UnsupportedMediaTypeException("Unsupported media type");
+      }
+
+      return xml.createResponse(
+          null,
+          FSManager.instance().readFile(Constants.get(ConstantKey.SERVICES), acceptType),
+          null, acceptType);
+    } catch (Exception e) {
+      return xml.createFaultResponse(accept, e);
+    }
+  }
+
+  /**
+   * Provide sample getMetadata().
+   *
+   * @return getMetadata().
+   */
+  @GET
+  @Path("/$metadata")
+  @Produces(MediaType.APPLICATION_XML)
+  public Response getMetadata() {
+    return getMetadata(Constants.get(ConstantKey.METADATA));
+  }
+
+  protected Response getMetadata(final String filename) {
+    try {
+      return xml.createResponse(null, FSManager.instance().readRes(filename, Accept.XML), null, Accept.XML);
+    } catch (Exception e) {
+      return xml.createFaultResponse(Accept.XML.toString(), e);
+    }
   }
 
   @GET
   @Path("/redirect/{name}({id})")
-  public Response conformanceRedirect(
-      @Context final UriInfo uriInfo,
-      @PathParam("name") final String name,
-      @PathParam("id") final String id) {
+  public Response conformanceRedirect(@Context final UriInfo uriInfo) {
     return Response.temporaryRedirect(
         URI.create(uriInfo.getRequestUri().toASCIIString().replace("/redirect", ""))).build();
   }
@@ -128,7 +214,7 @@ public class Services extends AbstractServices {
 
     try {
       if (CROSSJOIN_PATTERN.matcher("$crossjoin(" + elements + ")?$filter=" + filter).matches()) {
-        final InputStream feed = FSManager.instance(version).readFile("crossjoin", Accept.JSON);
+        final InputStream feed = FSManager.instance().readFile("crossjoin", Accept.JSON);
 
         return xml.createResponse(feed, null, Accept.JSON_FULLMETA);
       } else {
@@ -141,9 +227,7 @@ public class Services extends AbstractServices {
 
   @GET
   @Path("/relatedEntitySelect/{path:.*}")
-  public Response relatedEntitySelect(
-      @PathParam("path") final String path,
-      @QueryParam("$expand") final String expand) {
+  public Response relatedEntitySelect(@QueryParam("$expand") final String expand) {
 
     if (RELENTITY_SELECT_PATTERN.matcher(expand).matches()) {
       return xml.createResponse(null, null, Accept.JSON_FULLMETA);
@@ -177,7 +261,6 @@ public class Services extends AbstractServices {
   @PUT
   @Path("/People(1)/Parent")
   public Response changeSingleValuedNavigationPropertyReference(
-      @Context final UriInfo uriInfo,
       @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept,
       @HeaderParam("Content-Type") @DefaultValue(StringUtils.EMPTY) final String contentType,
       final String content) {
@@ -196,39 +279,95 @@ public class Services extends AbstractServices {
   }
 
   @POST
-  @Path("/async/$batch")
-  public Response async(
-      @Context final UriInfo uriInfo,
+  @Path("/$batch")
+  @Consumes(MULTIPART_MIXED)
+  @Produces(APPLICATION_OCTET_STREAM + ";boundary=" + BOUNDARY)
+  public Response batch(
       @HeaderParam("Prefer") @DefaultValue(StringUtils.EMPTY) final String prefer,
       final @Multipart MultipartBody attachment) {
+    try {
+      final boolean continueOnError = prefer.contains("odata.continue-on-error");
+      return xml.createBatchResponse(
+          exploreMultipart(attachment.getAllAttachments(), BOUNDARY, continueOnError));
+    } catch (IOException e) {
+      return xml.createFaultResponse(Accept.XML.toString(), e);
+    }
+  }
+
+  // ----------------------------------------------
+  // just for non nullable property test into PropertyTestITCase
+  // ----------------------------------------------
+  @PATCH
+  @Path("/Driver('2')")
+  public Response patchDriver() {
+    return xml.createFaultResponse(Accept.JSON_FULLMETA.toString(), new Exception("Non nullable properties"));
+  }
+
+  @GET
+  @Path("/StoredPIs(1000)")
+  public Response getStoredPI(@Context final UriInfo uriInfo) {
+    final Entity entity = new Entity();
+    entity.setType("Microsoft.Test.OData.Services.ODataWCFService.StoredPI");
+    final Property id = new Property();
+    id.setType("Edm.Int32");
+    id.setName("StoredPIID");
+    id.setValue(ValueType.PRIMITIVE, 1000);
+    entity.getProperties().add(id);
+    final Link edit = new Link();
+    edit.setHref(uriInfo.getRequestUri().toASCIIString());
+    edit.setRel("edit");
+    edit.setTitle("StoredPI");
+    entity.setEditLink(edit);
+
+    final ByteArrayOutputStream content = new ByteArrayOutputStream();
+    final OutputStreamWriter writer = new OutputStreamWriter(content, Constants.ENCODING);
+    try {
+      jsonSerializer.write(writer, new ResWrap<Entity>((URI) null, null, entity));
+      return xml.createResponse(new ByteArrayInputStream(content.toByteArray()), null, Accept.JSON_FULLMETA);
+    } catch (Exception e) {
+      LOG.error("While creating StoredPI", e);
+      return xml.createFaultResponse(Accept.JSON_FULLMETA.toString(), e);
+    }
+  }
+
+  @PATCH
+  @Path("/StoredPIs(1000)")
+  public Response patchStoredPI() {
+    // just for non nullable property test into PropertyTestITCase
+    return xml.createFaultResponse(Accept.JSON_FULLMETA.toString(), new Exception("Non nullable properties"));
+  }
+
+  @POST
+  @Path("/async/$batch")
+  public Response async(@Context final UriInfo uriInfo) {
 
     try {
       final ByteArrayOutputStream bos = new ByteArrayOutputStream();
       bos.write("HTTP/1.1 200 Ok".getBytes());
-      bos.write(CRLF);
+      bos.write(Constants.CRLF);
       bos.write("OData-Version: 4.0".getBytes());
-      bos.write(CRLF);
+      bos.write(Constants.CRLF);
       bos.write(("Content-Type: " + ContentType.APPLICATION_OCTET_STREAM + ";boundary=" + BOUNDARY).getBytes());
-      bos.write(CRLF);
-      bos.write(CRLF);
+      bos.write(Constants.CRLF);
+      bos.write(Constants.CRLF);
 
       bos.write(("--" + BOUNDARY).getBytes());
-      bos.write(CRLF);
+      bos.write(Constants.CRLF);
       bos.write("Content-Type: application/http".getBytes());
-      bos.write(CRLF);
+      bos.write(Constants.CRLF);
       bos.write("Content-Transfer-Encoding: binary".getBytes());
-      bos.write(CRLF);
-      bos.write(CRLF);
+      bos.write(Constants.CRLF);
+      bos.write(Constants.CRLF);
 
       bos.write("HTTP/1.1 202 Accepted".getBytes());
-      bos.write(CRLF);
+      bos.write(Constants.CRLF);
       bos.write("Location: http://service-root/async-monitor".getBytes());
-      bos.write(CRLF);
+      bos.write(Constants.CRLF);
       bos.write("Retry-After: 10".getBytes());
-      bos.write(CRLF);
-      bos.write(CRLF);
+      bos.write(Constants.CRLF);
+      bos.write(Constants.CRLF);
       bos.write(("--" + BOUNDARY + "--").getBytes());
-      bos.write(CRLF);
+      bos.write(Constants.CRLF);
 
       final UUID uuid = UUID.randomUUID();
       providedAsync.put(uuid.toString(), bos.toString(Constants.ENCODING.toString()));
@@ -263,11 +402,13 @@ public class Services extends AbstractServices {
           ? Constants.get(ConstantKey.ENTITY)
           : Constants.get(ConstantKey.FEED));
 
-      final InputStream feed = FSManager.instance(version).readFile(path.toString(), acceptType);
+      final InputStream feed = FSManager.instance().readFile(path.toString(), acceptType);
 
       final StringBuilder builder = new StringBuilder();
-      builder.append("HTTP/1.1 200 Ok").append(new String(CRLF));
-      builder.append("Content-Type: ").append(accept).append(new String(CRLF)).append(new String(CRLF));
+      builder.append("HTTP/1.1 200 Ok").append(new String(Constants.CRLF));
+      builder.append("Content-Type: ").append(accept)
+          .append(new String(Constants.CRLF))
+          .append(new String(Constants.CRLF));
       builder.append(IOUtils.toString(feed));
       IOUtils.closeQuietly(feed);
 
@@ -281,15 +422,80 @@ public class Services extends AbstractServices {
     }
   }
 
-  @Override
-  protected void setInlineCount(final EntityCollection entitySet, final String count) {
+  private void setInlineCount(final EntityCollection entitySet, final String count) {
     if ("true".equals(count)) {
       entitySet.setCount(entitySet.getEntities().size());
     }
   }
 
-  @Override
-  public InputStream exploreMultipart(
+  private Response bodyPartRequest(final MimeBodyPart body, final Map<String, String> references) throws Exception {
+    @SuppressWarnings("unchecked")
+    final Enumeration<Header> en = body.getAllHeaders();
+
+    Header header = en.nextElement();
+    final String request =
+        header.getName() + (StringUtils.isNotBlank(header.getValue()) ? ":" + header.getValue() : "");
+
+    final Matcher matcher = REQUEST_PATTERN.matcher(request);
+    final Matcher matcherRef = BATCH_REQUEST_REF_PATTERN.matcher(request);
+
+    final MultivaluedMap<String, String> headers = new MultivaluedHashMap<String, String>();
+
+    while (en.hasMoreElements()) {
+      header = en.nextElement();
+      headers.putSingle(header.getName(), header.getValue());
+    }
+
+    final Response res;
+    final String url;
+    final String method;
+
+    if (matcher.find()) {
+      url = matcher.group(2);
+      method = matcher.group(1);
+    } else if (matcherRef.find()) {
+      url = references.get(matcherRef.group(2)) + matcherRef.group(3);
+      method = matcherRef.group(1);
+    } else {
+      url = null;
+      method = null;
+    }
+
+    if (url == null) {
+      res = null;
+    } else {
+      final WebClient client = WebClient.create(url, "odatajclient", "odatajclient", null);
+      client.headers(headers);
+
+      if ("DELETE".equals(method)) {
+        res = client.delete();
+      } else {
+        final InputStream is = body.getDataHandler().getInputStream();
+        String content = IOUtils.toString(is);
+        IOUtils.closeQuietly(is);
+
+        final Matcher refs = REF_PATTERN.matcher(content);
+
+        while (refs.find()) {
+          content = content.replace(refs.group(1), references.get(refs.group(1)));
+        }
+
+        if ("PATCH".equals(method) || "MERGE".equals(method)) {
+          client.header("X-HTTP-METHOD", method);
+          res = client.invoke("POST", IOUtils.toInputStream(content));
+        } else {
+          res = client.invoke(method, IOUtils.toInputStream(content));
+        }
+      }
+
+      // When updating to CXF 3.0.1, uncomment the following line, see CXF-5865
+      // client.close();
+    }
+
+    return res;
+  }
+
+  private InputStream exploreMultipart(
       final List<Attachment> attachments, final String boundary, final boolean continueOnError)
       throws IOException {
 
@@ -349,9 +555,10 @@ public class Services extends AbstractServices {
             goon = continueOnError;
           }
         } else {
-          addItemIntro(bos);
+          addItemIntro(bos, null);
 
-          res = bodyPartRequest(new MimeBodyPart(obj.getDataHandler().getInputStream()));
+          res = bodyPartRequest(new MimeBodyPart(obj.getDataHandler().getInputStream()),
+              Collections.<String, String> emptyMap());
 
           if (res.getStatus() >= 400) {
             goon = continueOnError;
@@ -374,121 +581,131 @@ public class Services extends AbstractServices {
     return new ByteArrayInputStream(bos.toByteArray());
   }
 
-  @GET
-  @Path("/People/{type:.*}")
-  public Response getPeople(
-      @Context final UriInfo uriInfo,
-      @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept,
-      @PathParam("type") final String type,
-      @QueryParam("$top") @DefaultValue(StringUtils.EMPTY) final String top,
-      @QueryParam("$skip") @DefaultValue(StringUtils.EMPTY) final String skip,
-      @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format,
-      @QueryParam("$count") @DefaultValue(StringUtils.EMPTY) final String count,
-      @QueryParam("$filter") @DefaultValue(StringUtils.EMPTY) final String filter,
-      @QueryParam("$search") @DefaultValue(StringUtils.EMPTY) final String search,
-      @QueryParam("$orderby") @DefaultValue(StringUtils.EMPTY) final String orderby,
-      @QueryParam("$skiptoken") @DefaultValue(StringUtils.EMPTY) final String skiptoken) {
+  private void addItemIntro(final ByteArrayOutputStream bos, final String contentId) throws IOException {
+    bos.write("Content-Type: application/http".getBytes());
+    bos.write(Constants.CRLF);
+    bos.write("Content-Transfer-Encoding: binary".getBytes());
+    bos.write(Constants.CRLF);
 
-    return StringUtils.isBlank(filter) && StringUtils.isBlank(search)
-        ? NumberUtils.isNumber(type)
-            ? super.getEntityInternal(
-                uriInfo.getRequestUri().toASCIIString(), accept, "People", type, format, null, null)
-            : super.getEntitySet(accept, "People", type)
-        : super.getEntitySet(uriInfo, accept, "People", top, skip, format, count, filter, orderby, skiptoken, type);
+    if (StringUtils.isNotBlank(contentId)) {
+      bos.write(("Content-ID: " + contentId).getBytes());
+      bos.write(Constants.CRLF);
+    }
+
+    bos.write(Constants.CRLF);
   }
 
-  @GET
-  @Path("/Boss")
-  public Response getSingletonBoss(
-      @Context final UriInfo uriInfo,
-      @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept,
-      @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format) {
+  private void addChangesetItemIntro(
+      final ByteArrayOutputStream bos, final String contentId, final String cboundary) throws IOException {
+    bos.write(("--" + cboundary).getBytes());
+    bos.write(Constants.CRLF);
+    bos.write(("Content-ID: " + contentId).getBytes());
+    bos.write(Constants.CRLF);
+    addItemIntro(bos, null);
+  }
 
-    return getEntityInternal(
-        uriInfo.getRequestUri().toASCIIString(), accept, "Boss", StringUtils.EMPTY, format, null, null);
+  private void addSingleBatchResponse(
+      final Response response, final ByteArrayOutputStream bos) throws IOException {
+    addSingleBatchResponse(response, null, bos);
   }
 
-  @GET
-  @Path("/Company")
-  public Response getSingletonCompany(
-      @Context final UriInfo uriInfo,
-      @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept,
-      @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format) {
+  private void addSingleBatchResponse(
+      final Response response, final String contentId, final ByteArrayOutputStream bos) throws IOException {
+    bos.write("HTTP/1.1 ".getBytes());
+    bos.write(String.valueOf(response.getStatusInfo().getStatusCode()).getBytes());
+    bos.write(" ".getBytes());
+    bos.write(response.getStatusInfo().getReasonPhrase().getBytes());
+    bos.write(Constants.CRLF);
 
-    return getEntityInternal(
-        uriInfo.getRequestUri().toASCIIString(), accept, "Company", StringUtils.EMPTY, format, null, null);
+    for (Map.Entry<String, List<Object>> header : response.getHeaders().entrySet()) {
+      final StringBuilder builder = new StringBuilder();
+      for (Object value : header.getValue()) {
+        if (builder.length() > 0) {
+          builder.append(", ");
+        }
+        builder.append(value.toString());
+      }
+      builder.insert(0, ": ").insert(0, header.getKey());
+      bos.write(builder.toString().getBytes());
+      bos.write(Constants.CRLF);
+    }
+
+    if (StringUtils.isNotBlank(contentId)) {
+      bos.write(("Content-ID: " + contentId).getBytes());
+      bos.write(Constants.CRLF);
+    }
+
+    bos.write(Constants.CRLF);
+
+    final Object entity = response.getEntity();
+    if (entity != null) {
+      bos.write(IOUtils.toByteArray((InputStream) entity));
+      bos.write(Constants.CRLF);
+    }
+
+    bos.write(Constants.CRLF);
   }
 
-  @PATCH
-  @Path("/Company")
-  @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_ATOM_XML, MediaType.APPLICATION_JSON })
-  @Consumes({ MediaType.APPLICATION_ATOM_XML, MediaType.APPLICATION_JSON })
-  public Response patchSingletonCompany(
-      @Context final UriInfo uriInfo,
-      @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept,
-      @HeaderParam("Content-Type") @DefaultValue(StringUtils.EMPTY) final String contentType,
-      @HeaderParam("Prefer") @DefaultValue(StringUtils.EMPTY) final String prefer,
-      @HeaderParam("If-Match") @DefaultValue(StringUtils.EMPTY) final String ifMatch,
-      final String changes) {
+  protected void addErrorBatchResponse(final Exception e, final ByteArrayOutputStream bos)
+      throws IOException {
+    addErrorBatchResponse(e, null, bos);
+  }
 
-    return super.patchEntity(uriInfo, accept, contentType, prefer, ifMatch, "Company", StringUtils.EMPTY, changes);
+  protected void addErrorBatchResponse(final Exception e, final String contentId, final ByteArrayOutputStream bos)
+      throws IOException {
+    addSingleBatchResponse(xml.createFaultResponse(Accept.XML.toString(), e), contentId, bos);
   }
 
+  /**
+   * Retrieve entities from the given entity set and the given type.
+   *
+   * @param accept Accept header.
+   * @param name entity set.
+   * @param type entity type.
+   * @return entity set.
+   */
   @GET
-  @Path("/Customers")
-  public Response getCustomers(
-      @Context final UriInfo uriInfo,
+  @Path("/{name}/{type:[a-zA-Z].*}")
+  public Response getEntitySet(
       @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept,
-      @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format,
-      @HeaderParam("Prefer") @DefaultValue(StringUtils.EMPTY) final String prefer,
-      @QueryParam("$deltatoken") @DefaultValue(StringUtils.EMPTY) final String deltatoken) {
+      @PathParam("name") final String name,
+      @PathParam("type") final String type) {
 
     try {
-      final Accept acceptType;
-      if (StringUtils.isNotBlank(format)) {
-        acceptType = Accept.valueOf(format.toUpperCase());
-      } else {
-        acceptType = Accept.parse(accept);
+      final Accept acceptType = Accept.parse(accept);
+      if (acceptType == Accept.XML || acceptType == Accept.TEXT) {
+        throw new UnsupportedMediaTypeException("Unsupported media type");
       }
 
-      final InputStream output;
-      if (StringUtils.isBlank(deltatoken)) {
-        final InputStream input = (InputStream) getEntitySet(
-            uriInfo, accept, "Customers", null, null, format, null, null, null, null).getEntity();
-        final EntityCollection entitySet = xml.readEntitySet(acceptType, input);
-
-        boolean trackChanges = prefer.contains("odata.track-changes");
-        if (trackChanges) {
-          entitySet.setDeltaLink(URI.create("Customers?$deltatoken=8015"));
-        }
+      final String basePath = name + File.separatorChar;
+      final StringBuilder path = new StringBuilder(name).
+          append(File.separatorChar).append(type).
+          append(File.separatorChar);
 
-        output = xml.writeEntitySet(acceptType, new ResWrap<EntityCollection>(
-            URI.create(Constants.get(ConstantKey.ODATA_METADATA_PREFIX) + "Customers"),
-            null,
-            entitySet));
-      } else {
-        output = FSManager.instance(version).readFile("delta", acceptType);
-      }
+      path.append(metadata.getEntitySet(name).isSingleton()
+          ? Constants.get(ConstantKey.ENTITY)
+              : Constants.get(ConstantKey.FEED));
 
-      final Response response = xml.createResponse(
-          null,
-          output,
-          null,
-          acceptType);
-      if (StringUtils.isNotBlank(prefer)) {
-        response.getHeaders().put("Preference-Applied", Collections.<Object> singletonList(prefer));
-      }
-      return response;
+      final InputStream feed = FSManager.instance().readFile(path.toString(), acceptType);
+      return xml.createResponse(null, feed, Commons.getETag(basePath), acceptType);
     } catch (Exception e) {
       return xml.createFaultResponse(accept, e);
     }
   }
 
   @GET
-  @Path("/Company/Microsoft.Test.OData.Services.ODataWCFService.GetEmployeesCount{paren:[\\(\\)]*}")
-  public Response functionGetEmployeesCount(
+  @Path("/{name}/{type:[a-zA-Z].*}")
+  public Response getEntitySet(@Context final UriInfo uriInfo,
       @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept,
-      @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format) {
+      @PathParam("name") final String name,
+      @QueryParam("$top") @DefaultValue(StringUtils.EMPTY) final String top,
+      @QueryParam("$skip") @DefaultValue(StringUtils.EMPTY) final String skip,
+      @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format,
+      @QueryParam("$count") @DefaultValue(StringUtils.EMPTY) final String count,
+      @QueryParam("$filter") @DefaultValue(StringUtils.EMPTY) final String filter,
+      @QueryParam("$orderby") @DefaultValue(StringUtils.EMPTY) final String orderby,
+      @QueryParam("$skiptoken") @DefaultValue(StringUtils.EMPTY) final String skiptoken,
+      @PathParam("type") final String type) {
 
     try {
       final Accept acceptType;
@@ -498,111 +715,450 @@ public class Services extends AbstractServices {
         acceptType = Accept.parse(accept);
       }
 
-      final Property property = new Property();
-      property.setType("Edm.Int32");
-      property.setValue(ValueType.PRIMITIVE, 2);
-      final ResWrap<Property> container = new ResWrap<Property>(
-          URI.create(Constants.get(ConstantKey.ODATA_METADATA_PREFIX) + property.getType()), null,
-          property);
+      final String location = uriInfo.getRequestUri().toASCIIString();
+      try {
+        // search for function ...
+        final InputStream func = FSManager.instance().readFile(name, acceptType);
+        return xml.createResponse(location, func, null, acceptType);
+      } catch (NotFoundException e) {
+        if (acceptType == Accept.XML || acceptType == Accept.TEXT) {
+          throw new UnsupportedMediaTypeException("Unsupported media type");
+        }
 
-      return xml.createResponse(
-          null,
-          xml.writeProperty(acceptType, container),
-          null,
-          acceptType);
-    } catch (Exception e) {
-      return xml.createFaultResponse(accept, e);
-    }
-  }
+        // search for entitySet ...
+        final String basePath = name + File.separatorChar;
 
-  @POST
-  @Path("/Company/Microsoft.Test.OData.Services.ODataWCFService.IncreaseRevenue{paren:[\\(\\)]*}")
-  public Response actionIncreaseRevenue(
-      @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept,
-      @HeaderParam("Content-Type") @DefaultValue(StringUtils.EMPTY) final String contentType,
-      @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format,
-      final String param) {
+        final StringBuilder builder = new StringBuilder();
+        builder.append(basePath);
 
-    try {
-      final Accept acceptType;
-      if (StringUtils.isNotBlank(format)) {
-        acceptType = Accept.valueOf(format.toUpperCase());
-      } else {
-        acceptType = Accept.parse(accept);
-      }
+        if (type != null) {
+          builder.append(type).append(File.separatorChar);
+        }
 
-      final Accept contentTypeValue = Accept.parse(contentType);
-      final Entity entry = xml.readEntity(contentTypeValue, IOUtils.toInputStream(param, Constants.ENCODING));
+        if (StringUtils.isNotBlank(orderby)) {
+          builder.append(Constants.get(ConstantKey.ORDERBY)).append(File.separatorChar).
+          append(orderby).append(File.separatorChar);
+        }
 
-      return xml.createResponse(
-          null,
-          xml.writeProperty(acceptType, entry.getProperty("IncreaseValue")),
-          null,
-          acceptType);
+        if (StringUtils.isNotBlank(filter)) {
+          builder.append(Constants.get(ConstantKey.FILTER)).append(File.separatorChar).
+          append(filter.replaceAll("/", "."));
+        } else if (StringUtils.isNotBlank(skiptoken)) {
+          builder.append(Constants.get(ConstantKey.SKIP_TOKEN)).append(File.separatorChar).
+          append(skiptoken);
+        } else {
+          builder.append(metadata.getEntitySet(name).isSingleton()
+              ? Constants.get(ConstantKey.ENTITY)
+                  : Constants.get(ConstantKey.FEED));
+        }
+
+        final InputStream feed = FSManager.instance().readFile(builder.toString(), Accept.ATOM);
+
+        final ResWrap<EntityCollection> container = atomDeserializer.toEntitySet(feed);
+
+        setInlineCount(container.getPayload(), count);
+
+        final ByteArrayOutputStream content = new ByteArrayOutputStream();
+        final OutputStreamWriter writer = new OutputStreamWriter(content, Constants.ENCODING);
+
+        // -----------------------------------------------
+        // Evaluate $skip and $top
+        // -----------------------------------------------
+        List<Entity> entries = new ArrayList<Entity>(container.getPayload().getEntities());
+
+        if (StringUtils.isNotBlank(skip)) {
+          entries = entries.subList(Integer.valueOf(skip), entries.size());
+        }
+
+        if (StringUtils.isNotBlank(top)) {
+          entries = entries.subList(0, Integer.valueOf(top));
+        }
+
+        container.getPayload().getEntities().clear();
+        container.getPayload().getEntities().addAll(entries);
+        // -----------------------------------------------
+
+        if (acceptType == Accept.ATOM) {
+          atomSerializer.write(writer, container);
+        } else {
+          jsonSerializer.write(writer, container);
+        }
+        writer.flush();
+        writer.close();
+
+        return xml.createResponse(
+            location,
+            new ByteArrayInputStream(content.toByteArray()),
+            Commons.getETag(basePath),
+            acceptType);
+      }
     } catch (Exception e) {
       return xml.createFaultResponse(accept, e);
     }
   }
 
+  /**
+   * Retrieve entity set or function execution sample.
+   *
+   * @param accept Accept header.
+   * @param name entity set or function name.
+   * @param format format query option.
+   * @param count count query option.
+   * @param filter filter query option.
+   * @param orderby orderby query option.
+   * @param skiptoken skiptoken query option.
+   * @return entity set or function result.
+   */
   @GET
-  @Path("/Products({entityId})/Microsoft.Test.OData.Services.ODataWCFService.GetProductDetails({param:.*})")
-  public Response functionGetProductDetails(
+  @Path("/{name}")
+  public Response getEntitySet(
+      @Context final UriInfo uriInfo,
+      @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept,
+      @PathParam("name") final String name,
+      @QueryParam("$top") @DefaultValue(StringUtils.EMPTY) final String top,
+      @QueryParam("$skip") @DefaultValue(StringUtils.EMPTY) final String skip,
+      @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format,
+      @QueryParam("$count") @DefaultValue(StringUtils.EMPTY) final String count,
+      @QueryParam("$filter") @DefaultValue(StringUtils.EMPTY) final String filter,
+      @QueryParam("$orderby") @DefaultValue(StringUtils.EMPTY) final String orderby,
+      @QueryParam("$skiptoken") @DefaultValue(StringUtils.EMPTY) final String skiptoken) {
+
+    return getEntitySet(uriInfo, accept, name, top, skip, format, count, filter, orderby, skiptoken, null);
+  }
+
+  @GET
+  @Path("/Person({entityId})")
+  public Response getPerson(
+      @Context final UriInfo uriInfo,
+      @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept,
+      @PathParam("entityId") final String entityId,
+      @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format) {
+
+    final Map.Entry<Accept, AbstractUtilities> utils = getUtilities(accept, format);
+
+    final Response internal = getEntityInternal(
+        uriInfo.getRequestUri().toASCIIString(), accept, "Person", entityId, format, null, null);
+    if (internal.getStatus() == 200) {
+      InputStream entity = (InputStream) internal.getEntity();
+      try {
+        if (utils.getKey() == Accept.JSON_FULLMETA || utils.getKey() == Accept.ATOM) {
+          entity = utils.getValue().addOperation(entity, "Sack", "#DefaultContainer.Sack",
+              uriInfo.getAbsolutePath().toASCIIString()
+              + "/Microsoft.Test.OData.Services.AstoriaDefaultService.SpecialEmployee/Sack");
+        }
+
+        return utils.getValue().createResponse(
+            uriInfo.getRequestUri().toASCIIString(),
+            entity,
+            internal.getHeaderString("ETag"),
+            utils.getKey());
+      } catch (Exception e) {
+        LOG.error("Error retrieving entity", e);
+        return xml.createFaultResponse(accept, e);
+      }
+    } else {
+      return internal;
+    }
+  }
+
+  @GET
+  @Path("/Product({entityId})")
+  public Response getProduct(
+      @Context final UriInfo uriInfo,
+      @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept,
+      @PathParam("entityId") final String entityId,
+      @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format) {
+
+    final Map.Entry<Accept, AbstractUtilities> utils = getUtilities(accept, format);
+
+    final Response internal = getEntityInternal(
+        uriInfo.getRequestUri().toASCIIString(), accept, "Product", entityId, format, null, null);
+    if (internal.getStatus() == 200) {
+      InputStream entity = (InputStream) internal.getEntity();
+      try {
+        if (utils.getKey() == Accept.JSON_FULLMETA || utils.getKey() == Accept.ATOM) {
+          entity = utils.getValue().addOperation(entity,
+              "ChangeProductDimensions", "#DefaultContainer.ChangeProductDimensions",
+              uriInfo.getAbsolutePath().toASCIIString() + "/ChangeProductDimensions");
+        }
+
+        return utils.getValue().createResponse(
+            uriInfo.getRequestUri().toASCIIString(),
+            entity,
+            internal.getHeaderString("ETag"),
+            utils.getKey());
+      } catch (Exception e) {
+        LOG.error("Error retrieving entity", e);
+        return xml.createFaultResponse(accept, e);
+      }
+    } else {
+      return internal;
+    }
+  }
+
+  @GET
+  @Path("/ComputerDetail({entityId})")
+  public Response getComputerDetail(
+      @Context final UriInfo uriInfo,
       @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept,
       @PathParam("entityId") final String entityId,
       @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format) {
 
+    final Map.Entry<Accept, AbstractUtilities> utils = getUtilities(accept, format);
+
+    final Response internal = getEntityInternal(
+        uriInfo.getRequestUri().toASCIIString(), accept, "ComputerDetail", entityId, format, null, null);
+    if (internal.getStatus() == 200) {
+      InputStream entity = (InputStream) internal.getEntity();
+      try {
+        if (utils.getKey() == Accept.JSON_FULLMETA || utils.getKey() == Accept.ATOM) {
+          entity = utils.getValue().addOperation(entity,
+              "ResetComputerDetailsSpecifications", "#DefaultContainer.ResetComputerDetailsSpecifications",
+              uriInfo.getAbsolutePath().toASCIIString() + "/ResetComputerDetailsSpecifications");
+        }
+
+        return utils.getValue().createResponse(
+            uriInfo.getRequestUri().toASCIIString(),
+            entity,
+            internal.getHeaderString("ETag"),
+            utils.getKey());
+      } catch (Exception e) {
+        LOG.error("Error retrieving entity", e);
+        return xml.createFaultResponse(accept, e);
+      }
+    } else {
+      return internal;
+    }
+  }
+
+  /**
+   * Retrieve entity sample.
+   *
+   * @param accept Accept header.
+   * @param entitySetName Entity set name.
+   * @param entityId entity id.
+   * @param format format query option.
+   * @param expand expand query option.
+   * @param select select query option.
+   * @return entity.
+   */
+  @GET
+  @Path("/{entitySetName}({entityId})")
+  public Response getEntity(
+      @Context final UriInfo uriInfo,
+      @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept,
+      @PathParam("entitySetName") final String entitySetName,
+      @PathParam("entityId") final String entityId,
+      @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format,
+      @QueryParam("$expand") @DefaultValue(StringUtils.EMPTY) final String expand,
+      @QueryParam("$select") @DefaultValue(StringUtils.EMPTY) final String select) {
+
+    return getEntityInternal(
+        uriInfo.getRequestUri().toASCIIString(), accept, entitySetName, entityId, format, expand, select);
+  }
+
+  protected Response getEntityInternal(
+      final String location,
+      final String accept,
+      final String entitySetName,
+      final String entityId,
+      final String format,
+      final String expand,
+      final String select) {
+
     try {
-      final Accept acceptType;
-      if (StringUtils.isNotBlank(format)) {
-        acceptType = Accept.valueOf(format.toUpperCase());
-      } else {
-        acceptType = Accept.parse(accept);
+      final Map.Entry<Accept, AbstractUtilities> utils = getUtilities(accept, format);
+
+      if (utils.getKey() == Accept.XML || utils.getKey() == Accept.TEXT) {
+        throw new UnsupportedMediaTypeException("Unsupported media type");
       }
 
-      final Entity entry = new Entity();
-      entry.setType("Microsoft.Test.OData.Services.ODataWCFService.ProductDetail");
-      final Property productId = new Property();
-      productId.setName("ProductID");
-      productId.setType("Edm.Int32");
-      productId.setValue(ValueType.PRIMITIVE, Integer.valueOf(entityId));
-      entry.getProperties().add(productId);
-      final Property productDetailId = new Property();
-      productDetailId.setName("ProductDetailID");
-      productDetailId.setType("Edm.Int32");
-      productDetailId.setValue(ValueType.PRIMITIVE, 2);
-      entry.getProperties().add(productDetailId);
+      final Map.Entry<String, InputStream> entityInfo =
+          utils.getValue().readEntity(entitySetName, entityId, Accept.ATOM);
 
-      final Link link = new Link();
-      link.setRel("edit");
-      link.setHref(URI.create(
-          Constants.get(ConstantKey.DEFAULT_SERVICE_URL)
-              + "ProductDetails(ProductID=6,ProductDetailID=1)").toASCIIString());
-      entry.setEditLink(link);
+      final InputStream entity = entityInfo.getValue();
 
-      final EntityCollection feed = new EntityCollection();
-      feed.getEntities().add(entry);
+      ResWrap<Entity> container = atomDeserializer.toEntity(entity);
+      if (container.getContextURL() == null) {
+        container = new ResWrap<Entity>(URI.create(Constants.get(ConstantKey.ODATA_METADATA_PREFIX)
+            + entitySetName + Constants.get(ConstantKey.ODATA_METADATA_ENTITY_SUFFIX)),
+            container.getMetadataETag(), container.getPayload());
+      }
+      final Entity entry = container.getPayload();
 
-      final ResWrap<EntityCollection> container = new ResWrap<EntityCollection>(
-          URI.create(Constants.get(ConstantKey.ODATA_METADATA_PREFIX) + "ProductDetail"), null,
-          feed);
+      if ((this instanceof KeyAsSegment)) {
+        final Link editLink = new Link();
+        editLink.setRel("edit");
+        editLink.setTitle(entitySetName);
+        editLink.setHref(Constants.get(ConstantKey.DEFAULT_SERVICE_URL) + entitySetName + "/" + entityId);
+
+        entry.setEditLink(editLink);
+      }
+
+      if (StringUtils.isNotBlank(select)) {
+        final List<String> properties = Arrays.asList(select.split(","));
+        final Set<Property> toBeRemoved = new HashSet<Property>();
+
+        for (Property property : entry.getProperties()) {
+          if (!properties.contains(property.getName())) {
+            toBeRemoved.add(property);
+          }
+        }
+
+        entry.getProperties().removeAll(toBeRemoved);
+
+        final Set<Link> linkToBeRemoved = new HashSet<Link>();
+
+        for (Link link : entry.getNavigationLinks()) {
+          if (!properties.contains(link.getTitle().replaceAll("@.*$", "")) && !properties.contains(link.getTitle())) {
+            linkToBeRemoved.add(link);
+          }
+        }
+
+        entry.getNavigationLinks().removeAll(linkToBeRemoved);
+      }
+
+      String tempExpand = expand;
+      if (StringUtils.isNotBlank(tempExpand)) {
+        tempExpand = StringUtils.substringBefore(tempExpand, "(");
+        final List<String> links = Arrays.asList(tempExpand.split(","));
+
+        final Map<Link, Link> replace = new HashMap<Link, Link>();
+
+        for (Link link : entry.getNavigationLinks()) {
+          if (links.contains(link.getTitle())) {
+            // expand link
+            final Link rep = new Link();
+            rep.setHref(link.getHref());
+            rep.setRel(link.getRel());
+            rep.setTitle(link.getTitle());
+            rep.setType(link.getType());
+            if (link.getType().equals(Constants.get(ConstantKey.ATOM_LINK_ENTRY))) {
+              // inline entry
+              final Entity inline = atomDeserializer.toEntity(
+                  xml.expandEntity(entitySetName, entityId, link.getTitle())).getPayload();
+              rep.setInlineEntity(inline);
+            } else if (link.getType().equals(Constants.get(ConstantKey.ATOM_LINK_FEED))) {
+              // inline feed
+              final EntityCollection inline = atomDeserializer.toEntitySet(
+                  xml.expandEntity(entitySetName, entityId, link.getTitle())).getPayload();
+              rep.setInlineEntitySet(inline);
+            }
+            replace.put(link, rep);
+          }
+        }
+
+        for (Map.Entry<Link, Link> link : replace.entrySet()) {
+          entry.getNavigationLinks().remove(link.getKey());
+          entry.getNavigationLinks().add(link.getValue());
+        }
+      }
 
       return xml.createResponse(
-          null,
-          xml.writeEntitySet(acceptType, container),
-          null,
-          acceptType);
+          location,
+          xml.writeEntity(utils.getKey(), container),
+          Commons.getETag(entityInfo.getKey()),
+          utils.getKey());
     } catch (Exception e) {
+      LOG.error("Error retrieving entity", e);
       return xml.createFaultResponse(accept, e);
     }
   }
 
-  @POST
-  @Path("/Products({entityId})/Microsoft.Test.OData.Services.ODataWCFService.AddAccessRight{paren:[\\(\\)]*}")
-  public Response actionAddAccessRight(
+  @GET
+  @Path("/{entitySetName}({entityId})/$value")
+  public Response getMediaEntity(
+      @Context final UriInfo uriInfo,
+      @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept,
+      @PathParam("entitySetName") final String entitySetName,
+      @PathParam("entityId") final String entityId) {
+
+    try {
+      if (!accept.contains("*/*") && !accept.contains("application/octet-stream")) {
+        throw new UnsupportedMediaTypeException("Unsupported media type");
+      }
+
+      final AbstractUtilities utils = getUtilities(null);
+      final Map.Entry<String, InputStream> entityInfo = utils.readMediaEntity(entitySetName, entityId);
+      return utils.createResponse(
+          uriInfo.getRequestUri().toASCIIString(),
+          entityInfo.getValue(),
+          Commons.getETag(entityInfo.getKey()),
+          null);
+
+    } catch (Exception e) {
+      LOG.error("Error retrieving entity", e);
+      return xml.createFaultResponse(accept, e);
+    }
+  }
+
+  @GET
+  @Path("/People/{type:.*}")
+  public Response getPeople(
+      @Context final UriInfo uriInfo,
+      @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept,
+      @PathParam("type") final String type,
+      @QueryParam("$top") @DefaultValue(StringUtils.EMPTY) final String top,
+      @QueryParam("$skip") @DefaultValue(StringUtils.EMPTY) final String skip,
+      @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format,
+      @QueryParam("$count") @DefaultValue(StringUtils.EMPTY) final String count,
+      @QueryParam("$filter") @DefaultValue(StringUtils.EMPTY) final String filter,
+      @QueryParam("$search") @DefaultValue(StringUtils.EMPTY) final String search,
+      @QueryParam("$orderby") @DefaultValue(StringUtils.EMPTY) final String orderby,
+      @QueryParam("$skiptoken") @DefaultValue(StringUtils.EMPTY) final String skiptoken) {
+
+    return StringUtils.isBlank(filter) && StringUtils.isBlank(search) ?
+        NumberUtils.isNumber(type) ?
+            getEntityInternal(uriInfo.getRequestUri().toASCIIString(), accept, "People", type, format, null, null) :
+            getEntitySet(accept, "People", type) :
+        getEntitySet(uriInfo, accept, "People", top, skip, format, count, filter, orderby, skiptoken, type);
+  }
+
+  @GET
+  @Path("/Boss")
+  public Response getSingletonBoss(
+      @Context final UriInfo uriInfo,
+      @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept,
+      @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format) {
+
+    return getEntityInternal(
+        uriInfo.getRequestUri().toASCIIString(), accept, "Boss", StringUtils.EMPTY, format, null, null);
+  }
+
+  @GET
+  @Path("/Company")
+  public Response getSingletonCompany(
+      @Context final UriInfo uriInfo,
+      @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept,
+      @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format) {
+
+    return getEntityInternal(
+        uriInfo.getRequestUri().toASCIIString(), accept, "Company", StringUtils.EMPTY, format, null, null);
+  }
+
+  @PATCH
+  @Path("/Company")
+  @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_ATOM_XML, MediaType.APPLICATION_JSON })
+  @Consumes({ MediaType.APPLICATION_ATOM_XML, MediaType.APPLICATION_JSON })
+  public Response patchSingletonCompany(
+      @Context final UriInfo uriInfo,
       @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept,
       @HeaderParam("Content-Type") @DefaultValue(StringUtils.EMPTY) final String contentType,
+      @HeaderParam("Prefer") @DefaultValue(StringUtils.EMPTY) final String prefer,
+      @HeaderParam("If-Match") @DefaultValue(StringUtils.EMPTY) final String ifMatch,
+      final String changes) {
+
+    return patchEntityInternal(uriInfo, accept, contentType, prefer, ifMatch, "Company", StringUtils.EMPTY, changes);
+  }
+
+  @GET
+  @Path("/Customers")
+  public Response getCustomers(
+      @Context final UriInfo uriInfo,
+      @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept,
       @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format,
-      final String param) {
+      @HeaderParam("Prefer") @DefaultValue(StringUtils.EMPTY) final String prefer,
+      @QueryParam("$deltatoken") @DefaultValue(StringUtils.EMPTY) final String deltatoken) {
 
     try {
       final Accept acceptType;
@@ -612,236 +1168,1448 @@ public class Services extends AbstractServices {
         acceptType = Accept.parse(accept);
       }
 
-      final Accept contentTypeValue = Accept.parse(contentType);
-      final Entity entry = xml.readEntity(contentTypeValue, IOUtils.toInputStream(param, Constants.ENCODING));
-
-      assert 1 == entry.getProperties().size();
-      assert entry.getProperty("accessRight") != null;
+      final InputStream output;
+      if (StringUtils.isBlank(deltatoken)) {
+        final InputStream input = (InputStream) getEntitySet(
+            uriInfo, accept, "Customers", null, null, format, null, null, null, null).getEntity();
+        final EntityCollection entitySet = xml.readEntitySet(acceptType, input);
 
-      final Property property = entry.getProperty("accessRight");
-      property.setType("Microsoft.Test.OData.Services.ODataWCFService.AccessLevel");
+        boolean trackChanges = prefer.contains("odata.track-changes");
+        if (trackChanges) {
+          entitySet.setDeltaLink(URI.create("Customers?$deltatoken=8015"));
+        }
 
-      final ResWrap<Property> result = new ResWrap<Property>(
-          URI.create(Constants.get(ConstantKey.ODATA_METADATA_PREFIX) + property.getType()),
-          null, property);
+        output = xml.writeEntitySet(acceptType, new ResWrap<EntityCollection>(
+            URI.create(Constants.get(ConstantKey.ODATA_METADATA_PREFIX) + "Customers"),
+            null,
+            entitySet));
+      } else {
+        output = FSManager.instance().readFile("delta", acceptType);
+      }
 
-      return xml.createResponse(
+      final Response response = xml.createResponse(
           null,
-          xml.writeProperty(acceptType, result),
+          output,
           null,
           acceptType);
+      if (StringUtils.isNotBlank(prefer)) {
+        response.getHeaders().put("Preference-Applied", Collections.<Object> singletonList(prefer));
+      }
+      return response;
     } catch (Exception e) {
       return xml.createFaultResponse(accept, e);
     }
   }
 
   @POST
-  @Path("/Customers({personId})/Microsoft.Test.OData.Services.ODataWCFService.ResetAddress{paren:[\\(\\)]*}")
-  public Response actionResetAddress(
+  @Path("/{entitySetName}")
+  @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_ATOM_XML, MediaType.APPLICATION_JSON })
+  @Consumes({ MediaType.APPLICATION_ATOM_XML, MediaType.APPLICATION_JSON, MediaType.APPLICATION_OCTET_STREAM })
+  public Response postNewEntity(
       @Context final UriInfo uriInfo,
       @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept,
-      @PathParam("personId") final String personId,
+      @HeaderParam("Content-Type") @DefaultValue(StringUtils.EMPTY) final String contentType,
+      @HeaderParam("Prefer") @DefaultValue(StringUtils.EMPTY) final String prefer,
+      @PathParam("entitySetName") final String entitySetName,
+      final String entity) {
+
+    try {
+      final Accept acceptType = Accept.parse(accept);
+      if (acceptType == Accept.XML || acceptType == Accept.TEXT) {
+        throw new UnsupportedMediaTypeException("Unsupported media type");
+      }
+
+      final ResWrap<Entity> container;
+
+      final org.apache.olingo.fit.metadata.EntitySet entitySet = metadata.getEntitySet(entitySetName);
+
+      final Entity entry;
+      final String entityKey;
+      if (xml.isMediaContent(entitySetName)) {
+        entry = new Entity();
+        entry.setMediaContentType(ContentType.APPLICATION_OCTET_STREAM.toContentTypeString());
+        entry.setType(entitySet.getType());
+
+        entityKey = xml.getDefaultEntryKey(entitySetName, entry);
+
+        xml.addMediaEntityValue(entitySetName, entityKey, IOUtils.toInputStream(entity, Constants.ENCODING));
+
+        final Pair<String, EdmPrimitiveTypeKind> id = Commons.getMediaContent().get(entitySetName);
+        if (id != null) {
+          final Property prop = new Property();
+          prop.setName(id.getKey());
+          prop.setType(id.getValue().toString());
+          prop.setValue(ValueType.PRIMITIVE,
+              id.getValue() == EdmPrimitiveTypeKind.Int32
+              ? Integer.parseInt(entityKey)
+                  : id.getValue() == EdmPrimitiveTypeKind.Guid
+                  ? UUID.fromString(entityKey)
+                      : entityKey);
+          entry.getProperties().add(prop);
+        }
+
+        final Link editLink = new Link();
+        editLink.setHref(Commons.getEntityURI(entitySetName, entityKey));
+        editLink.setRel("edit");
+        editLink.setTitle(entitySetName);
+        entry.setEditLink(editLink);
+
+        entry.setMediaContentSource(URI.create(editLink.getHref() + "/$value"));
+
+        container = new ResWrap<Entity>((URI) null, null, entry);
+      } else {
+        final Accept contentTypeValue = Accept.parse(contentType);
+        if (Accept.ATOM == contentTypeValue) {
+          container = atomDeserializer.toEntity(IOUtils.toInputStream(entity, Constants.ENCODING));
+        } else {
+          container = jsonDeserializer.toEntity(IOUtils.toInputStream(entity, Constants.ENCODING));
+        }
+        entry = container.getPayload();
+        updateInlineEntities(entry);
+
+        entityKey = xml.getDefaultEntryKey(entitySetName, entry);
+      }
+
+      normalizeAtomEntry(entry, entitySetName, entityKey);
+
+      final ByteArrayOutputStream content = new ByteArrayOutputStream();
+      final OutputStreamWriter writer = new OutputStreamWriter(content, Constants.ENCODING);
+      atomSerializer.write(writer, container);
+      writer.flush();
+      writer.close();
+
+      final InputStream serialization =
+          xml.addOrReplaceEntity(entityKey, entitySetName, new ByteArrayInputStream(content.toByteArray()), entry);
+
+      ResWrap<Entity> result = atomDeserializer.toEntity(serialization);
+      result = new ResWrap<Entity>(
+          URI.create(Constants.get(ConstantKey.ODATA_METADATA_PREFIX)
+              + entitySetName + Constants.get(ConstantKey.ODATA_METADATA_ENTITY_SUFFIX)),
+              null, result.getPayload());
+
+      final String path = Commons.getEntityBasePath(entitySetName, entityKey);
+      FSManager.instance().putInMemory(result, path + Constants.get(ConstantKey.ENTITY));
+
+      final String location;
+
+      if ((this instanceof KeyAsSegment)) {
+        location = uriInfo.getRequestUri().toASCIIString() + "/" + entityKey;
+
+        final Link editLink = new Link();
+        editLink.setRel("edit");
+        editLink.setTitle(entitySetName);
+        editLink.setHref(location);
+
+        result.getPayload().setEditLink(editLink);
+      } else {
+        location = uriInfo.getRequestUri().toASCIIString() + "(" + entityKey + ")";
+      }
+
+      final Response response;
+      if ("return-no-content".equalsIgnoreCase(prefer)) {
+        response = xml.createResponse(
+            location,
+            null,
+            null,
+            acceptType,
+            Response.Status.NO_CONTENT);
+      } else {
+        response = xml.createResponse(
+            location,
+            xml.writeEntity(acceptType, result),
+            null,
+            acceptType,
+            Response.Status.CREATED);
+      }
+
+      if (StringUtils.isNotBlank(prefer)) {
+        response.getHeaders().put("Preference-Applied", Collections.<Object> singletonList(prefer));
+      }
+
+      return response;
+    } catch (Exception e) {
+      LOG.error("While creating new entity", e);
+      return xml.createFaultResponse(accept, e);
+    }
+  }
+
+  private void updateInlineEntities(final Entity entity) {
+    final String type = entity.getType();
+    EntityType entityType;
+    Map<String, NavigationProperty> navProperties = Collections.emptyMap();
+    if (type != null && type.length() > 0) {
+      entityType = metadata.getEntityOrComplexType(type);
+      navProperties = entityType.getNavigationPropertyMap();
+    }
+
+    for (Property property : entity.getProperties()) {
+      if (navProperties.containsKey(property.getName())) {
+        Link alink = new Link();
+        alink.setTitle(property.getName());
+        alink.getAnnotations().addAll(property.getAnnotations());
+
+        alink.setType(navProperties.get(property.getName()).isEntitySet()
+            ? Constants.get(ConstantKey.ATOM_LINK_FEED)
+                : Constants.get(ConstantKey.ATOM_LINK_ENTRY));
+
+        alink.setRel(Constants.get(ConstantKey.ATOM_LINK_REL) + property.getName());
+
+        if (property.isCollection()) {
+          EntityCollection inline = new EntityCollection();
+          for (Object value : property.asCollection()) {
+            Entity inlineEntity = new Entity();
+            inlineEntity.setType(navProperties.get(property.getName()).getType());
+            for (Property prop : ((ComplexValue) value).getValue()) {
+              inlineEntity.getProperties().add(prop);
+            }
+            inline.getEntities().add(inlineEntity);
+          }
+          alink.setInlineEntitySet(inline);
+        } else if (property.isComplex()) {
+          Entity inline = new Entity();
+          inline.setType(navProperties.get(property.getName()).getType());
+          for (Property prop : property.asComplex().getValue()) {
+            inline.getProperties().add(prop);
+          }
+          alink.setInlineEntity(inline);
+
+        } else {
+          throw new IllegalStateException("Invalid navigation property " + property);
+        }
+        entity.getNavigationLinks().add(alink);
+      }
+    }
+  }
+
+  private void normalizeAtomEntry(final Entity entry, final String entitySetName, final String entityKey) {
+    final org.apache.olingo.fit.metadata.EntitySet entitySet = metadata.getEntitySet(entitySetName);
+    final EntityType entityType = metadata.getEntityOrComplexType(entitySet.getType());
+    for (Map.Entry<String, org.apache.olingo.fit.metadata.Property> property : entityType.getPropertyMap().entrySet()) {
+      if (entry.getProperty(property.getKey()) == null && property.getValue().isNullable()) {
+        final Property prop = new Property();
+        prop.setName(property.getKey());
+        prop.setValue(ValueType.PRIMITIVE, null);
+        entry.getProperties().add(prop);
+      }
+    }
+
+    for (Map.Entry<String, NavigationProperty> property : entityType.getNavigationPropertyMap().entrySet()) {
+      boolean found = false;
+      for (Link link : entry.getNavigationLinks()) {
+        if (link.getTitle().equals(property.getKey())) {
+          found = true;
+        }
+      }
+
+      if (!found) {
+        final Link link = new Link();
+        link.setTitle(property.getKey());
+        link.setType(property.getValue().isEntitySet()
+            ? Constants.get(ConstantKey.ATOM_LINK_FEED)
+                : Constants.get(ConstantKey.ATOM_LINK_ENTRY));
+        link.setRel(Constants.get(ConstantKey.ATOM_LINK_REL) + property.getKey());
+        link.setHref(entitySetName + "(" + entityKey + ")/" + property.getKey());
+        entry.getNavigationLinks().add(link);
+      }
+    }
+  }
+
+  @GET
+  @Path("/Company/Microsoft.Test.OData.Services.ODataWCFService.GetEmployeesCount{paren:[\\(\\)]*}")
+  public Response functionGetEmployeesCount(
+      @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept,
+      @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format) {
+
+    try {
+      final Accept acceptType;
+      if (StringUtils.isNotBlank(format)) {
+        acceptType = Accept.valueOf(format.toUpperCase());
+      } else {
+        acceptType = Accept.parse(accept);
+      }
+
+      final Property property = new Property();
+      property.setType("Edm.Int32");
+      property.setValue(ValueType.PRIMITIVE, 2);
+      final ResWrap<Property> container = new ResWrap<Property>(
+          URI.create(Constants.get(ConstantKey.ODATA_METADATA_PREFIX) + property.getType()), null,
+          property);
+
+      return xml.createResponse(
+          null,
+          xml.writeProperty(acceptType, container),
+          null,
+          acceptType);
+    } catch (Exception e) {
+      return xml.createFaultResponse(accept, e);
+    }
+  }
+
+  @POST
+  @Path("/Person({entityId})/{type:.*}/Sack")
+  public Response actionSack(
+      @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept,
+      @PathParam("entityId") final String entityId,
+      @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format) {
+
+    final Map.Entry<Accept, AbstractUtilities> utils = getUtilities(accept, format);
+
+    if (utils.getKey() == Accept.XML || utils.getKey() == Accept.TEXT) {
+      throw new UnsupportedMediaTypeException("Unsupported media type");
+    }
+
+    try {
+      final Map.Entry<String, InputStream> entityInfo = xml.readEntity("Person", entityId, Accept.ATOM);
+
+      final InputStream entity = entityInfo.getValue();
+      final ResWrap<Entity> container = atomDeserializer.toEntity(entity);
+
+      container.getPayload().getProperty("Salary").setValue(ValueType.PRIMITIVE, 0);
+      container.getPayload().getProperty("Title").setValue(ValueType.PRIMITIVE, "[Sacked]");
+
+      final FSManager fsManager = FSManager.instance();
+      fsManager.putInMemory(xml.writeEntity(Accept.ATOM, container),
+          fsManager.getAbsolutePath(Commons.getEntityBasePath("Person", entityId) + Constants.get(
+              ConstantKey.ENTITY), Accept.ATOM));
+
+      return utils.getValue().createResponse(null, null, null, utils.getKey(), Response.Status.NO_CONTENT);
+    } catch (Exception e) {
+      return xml.createFaultResponse(accept, e);
+    }
+  }
+
+  @POST
+  @Path("/Person/{type:.*}/IncreaseSalaries")
+  public Response actionIncreaseSalaries(
+      @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept,
+      @PathParam("type") final String type,
+      final String body) {
+
+    final String name = "Person";
+    try {
+      final Accept acceptType = Accept.parse(accept);
+      if (acceptType == Accept.XML || acceptType == Accept.TEXT) {
+        throw new UnsupportedMediaTypeException("Unsupported media type");
+      }
+
+      final JsonNode tree = new ObjectMapper().readTree(body);
+      if (!tree.has("n")) {
+        throw new Exception("Missing parameter: n");
+      }
+      final int n = tree.get("n").asInt();
+
+      final StringBuilder path = new StringBuilder(name).
+          append(File.separatorChar).append(type).
+          append(File.separatorChar);
+
+      path.append(metadata.getEntitySet(name).isSingleton()
+          ? Constants.get(ConstantKey.ENTITY)
+              : Constants.get(ConstantKey.FEED));
+
+      final InputStream feed = FSManager.instance().readFile(path.toString(), acceptType);
+
+      final ByteArrayOutputStream copy = new ByteArrayOutputStream();
+      IOUtils.copy(feed, copy);
+      IOUtils.closeQuietly(feed);
+
+      String newContent = new String(copy.toByteArray(), "UTF-8");
+      final Pattern salary = Pattern.compile(acceptType == Accept.ATOM
+          ? "\\<d:Salary m:type=\"Edm.Int32\"\\>(-?\\d+)\\</d:Salary\\>"
+              : "\"Salary\":(-?\\d+),");
+      final Matcher salaryMatcher = salary.matcher(newContent);
+      while (salaryMatcher.find()) {
+        final Long newSalary = Long.valueOf(salaryMatcher.group(1)) + n;
+        newContent = newContent.
+            replaceAll("\"Salary\":" + salaryMatcher.group(1) + ",",
+                "\"Salary\":" + newSalary + ",").
+                replaceAll("\\<d:Salary m:type=\"Edm.Int32\"\\>" + salaryMatcher.group(1) + "</d:Salary\\>",
+                    "<d:Salary m:type=\"Edm.Int32\">" + newSalary + "</d:Salary>");
+      }
+
+      FSManager.instance().putInMemory(IOUtils.toInputStream(newContent, Constants.ENCODING),
+          FSManager.instance().getAbsolutePath(path.toString(), acceptType));
+
+      return xml.createResponse(null, null, null, acceptType, Response.Status.NO_CONTENT);
+    } catch (Exception e) {
+      return xml.createFaultResponse(accept, e);
+    }
+  }
+
+  @POST
+  @Path("/Product({entityId})/ChangeProductDimensions")
+  public Response actionChangeProductDimensions(
+      @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept,
+      @PathParam("entityId") final String entityId,
+      @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format,
+      final String argument) {
+
+    final Map.Entry<Accept, AbstractUtilities> utils = getUtilities(accept, format);
+
+    if (utils.getKey() == Accept.XML || utils.getKey() == Accept.TEXT) {
+      throw new UnsupportedMediaTypeException("Unsupported media type");
+    }
+
+    try {
+      final Map.Entry<String, InputStream> entityInfo = xml.readEntity("Product", entityId, Accept.ATOM);
+
+      final InputStream entity = entityInfo.getValue();
+      final ResWrap<Entity> container = atomDeserializer.toEntity(entity);
+
+      final Entity param = xml.readEntity(utils.getKey(), IOUtils.toInputStream(argument, Constants.ENCODING));
+
+      final Property property = param.getProperty("dimensions");
+      container.getPayload().getProperty("Dimensions").setValue(property.getValueType(), property.getValue());
+
+      final FSManager fsManager = FSManager.instance();
+      fsManager.putInMemory(xml.writeEntity(Accept.ATOM, container),
+          fsManager.getAbsolutePath(Commons.getEntityBasePath("Product", entityId) + Constants.get(
+              ConstantKey.ENTITY), Accept.ATOM));
+
+      return utils.getValue().createResponse(null, null, null, utils.getKey(), Response.Status.NO_CONTENT);
+    } catch (Exception e) {
+      return xml.createFaultResponse(accept, e);
+    }
+  }
+
+  @POST
+  @Path("/ComputerDetail({entityId})/ResetComputerDetailsSpecifications")
+  public Response actionResetComputerDetailsSpecifications(
+      @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept,
+      @PathParam("entityId") final String entityId,
+      @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format,
+      final String argument) {
+
+    final Map.Entry<Accept, AbstractUtilities> utils = getUtilities(accept, format);
+
+    if (utils.getKey() == Accept.XML || utils.getKey() == Accept.TEXT) {
+      throw new UnsupportedMediaTypeException("Unsupported media type");
+    }
+
+    try {
+      final Map.Entry<String, InputStream> entityInfo = xml.readEntity("ComputerDetail", entityId, Accept.ATOM);
+
+      final InputStream entity = entityInfo.getValue();
+      final ResWrap<Entity> container = atomDeserializer.toEntity(entity);
+
+      final Entity param = xml.readEntity(utils.getKey(), IOUtils.toInputStream(argument, Constants.ENCODING));
+
+      Property property = param.getProperty("specifications");
+      container.getPayload().getProperty("SpecificationsBag").setValue(property.getValueType(), property.getValue());
+      property = param.getProperty("purchaseTime");
+      container.getPayload().getProperty("PurchaseDate").setValue(property.getValueType(), property.getValue());
+
+      final FSManager fsManager = FSManager.instance();
+      fsManager.putInMemory(xml.writeEntity(Accept.ATOM, container),
+          fsManager.getAbsolutePath(Commons.getEntityBasePath("ComputerDetail", entityId) + Constants.get(
+              ConstantKey.ENTITY), Accept.ATOM));
+
+      return utils.getValue().createResponse(null, null, null, utils.getKey(), Response.Status.NO_CONTENT);
+    } catch (Exception e) {
+      return xml.createFaultResponse(accept, e);
+    }
+  }
+
+  @POST
+  @Path("/Company/Microsoft.Test.OData.Services.ODataWCFService.IncreaseRevenue{paren:[\\(\\)]*}")
+  public Response actionIncreaseRevenue(
+      @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept,
       @HeaderParam("Content-Type") @DefaultValue(StringUtils.EMPTY) final String contentType,
       @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format,
       final String param) {
 
     try {
+      final Accept acceptType;
+      if (StringUtils.isNotBlank(format)) {
+        acceptType = Accept.valueOf(format.toUpperCase());
+      } else {
+        acceptType = Accept.parse(accept);
+      }
+
       final Accept contentTypeValue = Accept.parse(contentType);
       final Entity entry = xml.readEntity(contentTypeValue, IOUtils.toInputStream(param, Constants.ENCODING));
 
-      assert 2 == entry.getProperties().size();
-      assert entry.getProperty("addresses") != null;
-      assert entry.getProperty("index") != null;
+      return xml.createResponse(
+          null,
+          xml.writeProperty(acceptType, entry.getProperty("IncreaseValue")),
+          null,
+          acceptType);
+    } catch (Exception e) {
+      return xml.createFaultResponse(accept, e);
+    }
+  }
+
+  @GET
+  @Path("/Products({entityId})/Microsoft.Test.OData.Services.ODataWCFService.GetProductDetails({param:.*})")
+  public Response functionGetProductDetails(
+      @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept,
+      @PathParam("entityId") final String entityId,
+      @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format) {
+
+    try {
+      final Accept acceptType;
+      if (StringUtils.isNotBlank(format)) {
+        acceptType = Accept.valueOf(format.toUpperCase());
+      } else {
+        acceptType = Accept.parse(accept);
+      }
+
+      final Entity entry = new Entity();
+      entry.setType("Microsoft.Test.OData.Services.ODataWCFService.ProductDetail");
+      final Property productId = new Property();
+      productId.setName("ProductID");
+      productId.setType("Edm.Int32");
+      productId.setValue(ValueType.PRIMITIVE, Integer.valueOf(entityId));
+      entry.getProperties().add(productId);
+      final Property productDetailId = new Property();
+      productDetailId.setName("ProductDetailID");
+      productDetailId.setType("Edm.Int32");
+      productDetailId.setValue(ValueType.PRIMITIVE, 2);
+      entry.getProperties().add(productDetailId);
+
+      final Link link = new Link();
+      link.setRel("edit");
+      link.setHref(URI.create(
+          Constants.get(ConstantKey.DEFAULT_SERVICE_URL)
+              + "ProductDetails(ProductID=6,ProductDetailID=1)").toASCIIString());
+      entry.setEditLink(link);
+
+      final EntityCollection feed = new EntityCollection();
+      feed.getEntities().add(entry);
+
+      final ResWrap<EntityCollection> container = new ResWrap<EntityCollection>(
+          URI.create(Constants.get(ConstantKey.ODATA_METADATA_PREFIX) + "ProductDetail"), null,
+          feed);
+
+      return xml.createResponse(
+          null,
+          xml.writeEntitySet(acceptType, container),
+          null,
+          acceptType);
+    } catch (Exception e) {
+      return xml.createFaultResponse(accept, e);
+    }
+  }
+
+  @POST
+  @Path("/Products({entityId})/Microsoft.Test.OData.Services.ODataWCFService.AddAccessRight{paren:[\\(\\)]*}")
+  public Response actionAddAccessRight(
+      @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept,
+      @HeaderParam("Content-Type") @DefaultValue(StringUtils.EMPTY) final String contentType,
+      @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format,
+      final String param) {
+
+    try {
+      final Accept acceptType;
+      if (StringUtils.isNotBlank(format)) {
+        acceptType = Accept.valueOf(format.toUpperCase());
+      } else {
+        acceptType = Accept.parse(accept);
+      }
+
+      final Accept contentTypeValue = Accept.parse(contentType);
+      final Entity entry = xml.readEntity(contentTypeValue, IOUtils.toInputStream(param, Constants.ENCODING));
+
+      assert 1 == entry.getProperties().size();
+      assert entry.getProperty("accessRight") != null;
+
+      final Property property = entry.getProperty("accessRight");
+      property.setType("Microsoft.Test.OData.Services.ODataWCFService.AccessLevel");
+
+      final ResWrap<Property> result = new ResWrap<Property>(
+          URI.create(Constants.get(ConstantKey.ODATA_METADATA_PREFIX) + property.getType()),
+          null, property);
+
+      return xml.createResponse(
+          null,
+          xml.writeProperty(acceptType, result),
+          null,
+          acceptType);
+    } catch (Exception e) {
+      return xml.createFaultResponse(accept, e);
+    }
+  }
+
+  @POST
+  @Path("/Customers({personId})/Microsoft.Test.OData.Services.ODataWCFService.ResetAddress{paren:[\\(\\)]*}")
+  public Response actionResetAddress(
+      @Context final UriInfo uriInfo,
+      @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept,
+      @PathParam("personId") final String personId,
+      @HeaderParam("Content-Type") @DefaultValue(StringUtils.EMPTY) final String contentType,
+      @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format,
+      final String param) {
+
+    try {
+      final Accept contentTypeValue = Accept.parse(contentType);
+      final Entity entry = xml.readEntity(contentTypeValue, IOUtils.toInputStream(param, Constants.ENCODING));
+
+      assert 2 == entry.getProperties().size();
+      assert entry.getProperty("addresses") != null;
+      assert entry.getProperty("index") != null;
+
+      return getEntityInternal(
+          uriInfo.getRequestUri().toASCIIString(), accept, "Customers", personId, format, null, null);
+    } catch (Exception e) {
+      return xml.createFaultResponse(accept, e);
+    }
+  }
+
+  @GET
+  @Path("/ProductDetails(ProductID={productId},ProductDetailID={productDetailId})"
+      + "/Microsoft.Test.OData.Services.ODataWCFService.GetRelatedProduct{paren:[\\(\\)]*}")
+  public Response functionGetRelatedProduct(
+      @Context final UriInfo uriInfo,
+      @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept,
+      @PathParam("productId") final String productId,
+      @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format) {
+
+    return getEntityInternal(
+        uriInfo.getRequestUri().toASCIIString(), accept, "Products", productId, format, null, null);
+  }
+
+  @POST
+  @Path("/Accounts({entityId})/Microsoft.Test.OData.Services.ODataWCFService.RefreshDefaultPI{paren:[\\(\\)]*}")
+  public Response actionRefreshDefaultPI(
+      @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept,
+      @HeaderParam("Content-Type") @DefaultValue(StringUtils.EMPTY) final String contentType,
+      @PathParam("entityId") final String entityId,
+      @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format,
+      final String param) {
+
+    try {
+      final Accept contentTypeValue = Accept.parse(contentType);
+      final Entity entry = xml.readEntity(contentTypeValue, IOUtils.toInputStream(param, Constants.ENCODING));
+
+      assert 1 == entry.getProperties().size();
+      assert entry.getProperty("newDate") != null;
+
+      return functionGetDefaultPI(accept, entityId, format);
+    } catch (Exception e) {
+      return xml.createFaultResponse(accept, e);
+    }
+  }
+
+  @GET
+  @Path("/Accounts({entityId})/Microsoft.Test.OData.Services.ODataWCFService.GetDefaultPI{paren:[\\(\\)]*}")
+  public Response functionGetDefaultPI(
+      @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept,
+      @PathParam("entityId") final String entityId,
+      @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format) {
+
+    return getContainedEntity(accept, entityId, "MyPaymentInstruments", entityId + "901", format);
+  }
+
+  @GET
+  @Path("/Accounts({entityId})/Microsoft.Test.OData.Services.ODataWCFService.GetAccountInfo{paren:[\\(\\)]*}")
+  public Response functionGetAccountInfo(
+      @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept,
+      @PathParam("entityId") final String entityId,
+      @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format) {
+
+    return getPath(accept, "Accounts", entityId, "AccountInfo", format);
+  }
+
+  @GET
+  @Path("/Accounts({entityId})/MyGiftCard/Microsoft.Test.OData.Services.ODataWCFService.GetActualAmount({param:.*})")
+  public Response functionGetActualAmount(
+      @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept,
+      @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format) {
+
+    try {
+      final Accept acceptType;
+      if (StringUtils.isNotBlank(format)) {
+        acceptType = Accept.valueOf(format.toUpperCase());
+      } else {
+        acceptType = Accept.parse(accept);
+      }
+
+      final Property property = new Property();
+      property.setType("Edm.Double");
+      property.setValue(ValueType.PRIMITIVE, 41.79);
+
+      final ResWrap<Property> container = new ResWrap<Property>((URI) null, null, property);
+
+      return xml.createResponse(
+          null,
+          xml.writeProperty(acceptType, container),
+          null,
+          acceptType);
+    } catch (Exception e) {
+      return xml.createFaultResponse(accept, e);
+    }
+  }
+
+  /**
+   * Retrieve entity reference sample.
+   *
+   * @param accept Accept header.
+   * @param path path.
+   * @param format format query option.
+   * @return entity reference or feed of entity reference.
+   */
+  @GET
+  @Path("/{path:.*}/$ref")
+  public Response getEntityReference(
+      @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept,
+      @PathParam("path") final String path,
+      @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format) {
+
+    try {
+      final Map.Entry<Accept, AbstractUtilities> utils = getUtilities(accept, format);
+
+      if (utils.getKey() == Accept.TEXT) {
+        throw new UnsupportedMediaTypeException("Unsupported media type");
+      }
+
+      final String filename = Base64.encodeBase64String(path.getBytes("UTF-8"));
+
+      return utils.getValue().createResponse(
+          FSManager.instance().readFile(Constants.get(ConstantKey.REF)
+              + File.separatorChar + filename, utils.getKey()),
+          null,
+          utils.getKey());
+    } catch (Exception e) {
+      LOG.error("Error retrieving entity", e);
+      return xml.createFaultResponse(accept, e);
+    }
+  }
+
+  @POST
+  @Path("/People")
+  @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_ATOM_XML, MediaType.APPLICATION_JSON })
+  @Consumes({ MediaType.APPLICATION_ATOM_XML, MediaType.APPLICATION_JSON, MediaType.APPLICATION_OCTET_STREAM })
+  public Response postPeople(
+      @Context final UriInfo uriInfo,
+      @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept,
+      @HeaderParam("Content-Type") @DefaultValue(StringUtils.EMPTY) final String contentType,
+      @HeaderParam("Prefer") @DefaultValue(StringUtils.EMPTY) final String prefer,
+      final String entity) {
+
+    if ("{\"@odata.type\":\"#Microsoft.Test.OData.Services.ODataWCFService.Person\"}".equals(entity)) {
+      return xml.createFaultResponse(accept, new BadRequestException());
+    }
+
+    return postNewEntity(uriInfo, accept, contentType, prefer, "People", entity);
+  }
+
+  private Response patchEntityInternal(final UriInfo uriInfo,
+      final String accept, final String contentType, final String prefer, final String ifMatch,
+      final String entitySetName, final String entityId, final String changes) {
+
+    try {
+      final Accept acceptType = Accept.parse(accept);
+
+      if (acceptType == Accept.XML || acceptType == Accept.TEXT) {
+        throw new UnsupportedMediaTypeException("Unsupported media type");
+      }
+
+      final Map.Entry<String, InputStream> entityInfo = xml.readEntity(entitySetName, entityId, Accept.ATOM);
+
+      final String etag = Commons.getETag(entityInfo.getKey());
+      if (StringUtils.isNotBlank(ifMatch) && !ifMatch.equals(etag)) {
+        throw new ConcurrentModificationException("Concurrent modification");
+      }
+
+      final Accept contentTypeValue = Accept.parse(contentType);
+
+      final Entity entryChanges;
+
+      if (contentTypeValue == Accept.XML || contentTypeValue == Accept.TEXT) {
+        throw new UnsupportedMediaTypeException("Unsupported media type");
+      } else if (contentTypeValue == Accept.ATOM) {
+        entryChanges = atomDeserializer.toEntity(
+            IOUtils.toInputStream(changes, Constants.ENCODING)).getPayload();
+      } else {
+        final ResWrap<Entity> jcont = jsonDeserializer.toEntity(IOUtils.toInputStream(changes, Constants.ENCODING));
+        entryChanges = jcont.getPayload();
+      }
+
+      final ResWrap<Entity> container = atomDeserializer.toEntity(entityInfo.getValue());
+
+      for (Property property : entryChanges.getProperties()) {
+        final Property _property = container.getPayload().getProperty(property.getName());
+        if (_property == null) {
+          container.getPayload().getProperties().add(property);
+        } else {
+          _property.setValue(property.getValueType(), property.getValue());
+        }
+      }
+
+      for (Link link : entryChanges.getNavigationLinks()) {
+        container.getPayload().getNavigationLinks().add(link);
+      }
+
+      final ByteArrayOutputStream content = new ByteArrayOutputStream();
+      final OutputStreamWriter writer = new OutputStreamWriter(content, Constants.ENCODING);
+      atomSerializer.write(writer, container);
+      writer.flush();
+      writer.close();
+
+      final InputStream res = xml.addOrReplaceEntity(
+          entityId, entitySetName, new ByteArrayInputStream(content.toByteArray()), container.getPayload());
+
+      final ResWrap<Entity> cres = atomDeserializer.toEntity(res);
+
+      normalizeAtomEntry(cres.getPayload(), entitySetName, entityId);
+
+      final String path = Commons.getEntityBasePath(entitySetName, entityId);
+      FSManager.instance().putInMemory(
+          cres, path + File.separatorChar + Constants.get(ConstantKey.ENTITY));
+
+      final Response response;
+      if ("return-content".equalsIgnoreCase(prefer)) {
+        response = xml.createResponse(
+            uriInfo.getRequestUri().toASCIIString(),
+            xml.readEntity(entitySetName, entityId, acceptType).getValue(),
+            null, acceptType, Response.Status.OK);
+      } else {
+        res.close();
+        response = xml.createResponse(
+            uriInfo.getRequestUri().toASCIIString(),
+            null,
+            null,
+            acceptType, Response.Status.NO_CONTENT);
+      }
+
+      if (StringUtils.isNotBlank(prefer)) {
+        response.getHeaders().put("Preference-Applied", Collections.<Object> singletonList(prefer));
+      }
+
+      return response;
+    } catch (Exception e) {
+      return xml.createFaultResponse(accept, e);
+    }
+  }
+
+  @PATCH
+  @Path("/{entitySetName}({entityId})")
+  @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_ATOM_XML, MediaType.APPLICATION_JSON })
+  @Consumes({ MediaType.APPLICATION_ATOM_XML, MediaType.APPLICATION_JSON })
+  public Response patchEntity(
+      @Context final UriInfo uriInfo,
+      @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept,
+      @HeaderParam("Content-Type") @DefaultValue(StringUtils.EMPTY) final String contentType,
+      @HeaderParam("Prefer") @DefaultValue(StringUtils.EMPTY) final String prefer,
+      @HeaderParam("If-Match") @DefaultValue(StringUtils.EMPTY) final String ifMatch,
+      @PathParam("entitySetName") final String entitySetName,
+      @PathParam("entityId") final String entityId,
+      final String changes) {
+
+    final Response response =
+        getEntityInternal(uriInfo.getRequestUri().toASCIIString(),
+            accept, entitySetName, entityId, accept, StringUtils.EMPTY, StringUtils.EMPTY);
+    return response.getStatus() >= 400 ?
+        postNewEntity(uriInfo, accept, contentType, prefer, entitySetName, changes) :
+        patchEntityInternal(uriInfo, accept, contentType, prefer, ifMatch, entitySetName, entityId, changes);
+  }
+
+  private Response replaceEntity(final UriInfo uriInfo,
+      final String accept, final String prefer,
+      final String entitySetName, final String entityId, final String entity) {
+
+    try {
+      final Accept acceptType = Accept.parse(accept);
+
+      if (acceptType == Accept.XML || acceptType == Accept.TEXT) {
+        throw new UnsupportedMediaTypeException("Unsupported media type");
+      }
+
+      final InputStream res = getUtilities(acceptType).addOrReplaceEntity(entityId, entitySetName,
+          IOUtils.toInputStream(entity, Constants.ENCODING),
+          xml.readEntity(acceptType, IOUtils.toInputStream(entity, Constants.ENCODING)));
+
+      final ResWrap<Entity> cres;
+      if (acceptType == Accept.ATOM) {
+        cres = atomDeserializer.toEntity(res);
+      } else {
+        cres = jsonDeserializer.toEntity(res);
+      }
+
+      final String path = Commons.getEntityBasePath(entitySetName, entityId);
+      FSManager.instance().putInMemory(
+          cres, path + File.separatorChar + Constants.get(ConstantKey.ENTITY));
+
+      final Response response;
+      if ("return-content".equalsIgnoreCase(prefer)) {
+        response = xml.createResponse(
+            uriInfo.getRequestUri().toASCIIString(),
+            xml.readEntity(entitySetName, entityId, acceptType).getValue(),
+            null,
+            acceptType,
+            Response.Status.OK);
+      } else {
+        res.close();
+        response = xml.createResponse(
+            uriInfo.getRequestUri().toASCIIString(),
+            null,
+            null,
+            acceptType,
+            Response.Status.NO_CONTENT);
+      }
+
+      if (StringUtils.isNotBlank(prefer)) {
+        response.getHeaders().put("Preference-Applied", Collections.<Object> singletonList(prefer));
+      }
+
+      return response;
+    } catch (Exception e) {
+      return xml.createFaultResponse(accept, e);
+    }
+  }
+
+  @PUT
+  @Path("/{entitySetName}({entityId})")
+  @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_ATOM_XML, MediaType.APPLICATION_JSON })
+  @Consumes({ MediaType.APPLICATION_ATOM_XML, MediaType.APPLICATION_JSON })
+  public Response replaceEntity(
+      @Context final UriInfo uriInfo,
+      @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept,
+      @HeaderParam("Content-Type") @DefaultValue(StringUtils.EMPTY) final String contentType,
+      @HeaderParam("Prefer") @DefaultValue(StringUtils.EMPTY) final String prefer,
+      @PathParam("entitySetName") final String entitySetName,
+      @PathParam("entityId") final String entityId,
+      final String entity) {
+
+    try {
+      getEntityInternal(uriInfo.getRequestUri().toASCIIString(),
+          accept, entitySetName, entityId, accept, StringUtils.EMPTY, StringUtils.EMPTY);
+      return replaceEntity(uriInfo, accept, prefer, entitySetName, entityId, entity);
+    } catch (NotFoundException e) {
+      return postNewEntity(uriInfo, accept, contentType, prefer, entitySetName, entityId);
+    }
+  }
+
+  private StringBuilder containedPath(final String entityId, final String containedEntitySetName) {
+    return new StringBuilder("Accounts").append(File.separatorChar).
+        append(entityId).append(File.separatorChar).
+        appen

<TRUNCATED>

[12/22] olingo-odata4 git commit: OLINGO-861, OLINGO-863, OLINGO-868, OLINGO-869 : Improvements to MetadataParser for annotation support

Posted by mi...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/6d94f0e3/lib/server-core-ext/src/test/resources/trippin.xml
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/src/test/resources/trippin.xml b/lib/server-core-ext/src/test/resources/trippin.xml
index 5970793..3266344 100644
--- a/lib/server-core-ext/src/test/resources/trippin.xml
+++ b/lib/server-core-ext/src/test/resources/trippin.xml
@@ -1,356 +1,458 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!--
-
-  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.
-
--->
+<!-- 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. -->
 <edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx">
-    <edmx:DataServices>
-        <Schema Namespace="Microsoft.OData.SampleService.Models.TripPin" xmlns="http://docs.oasis-open.org/odata/ns/edm">
-            <EnumType Name="PersonGender">
-                <Member Name="Male" Value="0" />
-                <Member Name="Female" Value="1" />
-                <Member Name="Unknown" Value="2" />
-            </EnumType>
-            <ComplexType Name="City">
-                <Property Name="CountryRegion" Type="Edm.String" Nullable="false" />
-                <Property Name="Name" Type="Edm.String" Nullable="false" />
-                <Property Name="Region" Type="Edm.String" Nullable="false" />
-            </ComplexType>
-            <ComplexType Name="Location" OpenType="true">
-                <Property Name="Address" Type="Edm.String" Nullable="false" />
-                <Property Name="City" Type="Microsoft.OData.SampleService.Models.TripPin.City" Nullable="false" />
-            </ComplexType>
-            <ComplexType Name="EventLocation" BaseType="Microsoft.OData.SampleService.Models.TripPin.Location" OpenType="true">
-                <Property Name="BuildingInfo" Type="Edm.String" />
-            </ComplexType>
-            <ComplexType Name="AirportLocation" BaseType="Microsoft.OData.SampleService.Models.TripPin.Location" OpenType="true">
-                <Property Name="Loc" Type="Edm.GeographyPoint" Nullable="false" SRID="4326" />
-            </ComplexType>
-            <EntityType Name="Photo" HasStream="true">
-                <Key>
-                    <PropertyRef Name="Id" />
-                </Key>
-                <Property Name="Id" Type="Edm.Int64" Nullable="false">
-                    <Annotation Term="Org.OData.Core.V1.Permissions">
-                        <EnumMember>Org.OData.Core.V1.Permission/Read</EnumMember>
-                    </Annotation>
-                </Property>
-                <Property Name="Name" Type="Edm.String" />
-                <Annotation Term="Org.OData.Core.V1.AcceptableMediaTypes">
-                    <Collection>
-                        <String>image/jpeg</String>
-                    </Collection>
-                </Annotation>
-            </EntityType>
-            <EntityType Name="Person" OpenType="true">
-                <Key>
-                    <PropertyRef Name="UserName" />
-                </Key>
-                <Property Name="UserName" Type="Edm.String" Nullable="false">
-                    <Annotation Term="Org.OData.Core.V1.Permissions">
-                        <EnumMember>Org.OData.Core.V1.Permission/Read</EnumMember>
-                    </Annotation>
-                </Property>
-                <Property Name="FirstName" Type="Edm.String" Nullable="true" />
-                <Property Name="LastName" Type="Edm.String" Nullable="false" />
-                <Property Name="Emails" Type="Collection(Edm.String)" />
-                <Property Name="AddressInfo" Type="Collection(Microsoft.OData.SampleService.Models.TripPin.Location)" />
-                <Property Name="Gender" Type="Microsoft.OData.SampleService.Models.TripPin.PersonGender" />
-                <Property Name="Concurrency" Type="Edm.Int64" Nullable="false">
-                    <Annotation Term="Org.OData.Core.V1.Computed" Bool="true" />
-                </Property>
-                <NavigationProperty Name="Friends" Type="Collection(Microsoft.OData.SampleService.Models.TripPin.Person)" />
-                <NavigationProperty Name="Trips" Type="Collection(Microsoft.OData.SampleService.Models.TripPin.Trip)" ContainsTarget="true" />
-                <NavigationProperty Name="Photo" Type="Microsoft.OData.SampleService.Models.TripPin.Photo" />
-            </EntityType>
-            <EntityType Name="Airline">
-                <Key>
-                    <PropertyRef Name="AirlineCode" />
-                </Key>
-                <Property Name="AirlineCode" Type="Edm.String" Nullable="false">
-                    <Annotation Term="Org.OData.Core.V1.Permissions">
-                        <EnumMember>Org.OData.Core.V1.Permission/Read</EnumMember>
-                    </Annotation>
-                </Property>
-                <Property Name="Name" Type="Edm.String" Nullable="false" />
-                <Property Name="Picture" Type="Edm.Stream" Nullable="true" />
-            </EntityType>
-            <EntityType Name="Airport">
-                <Key>
-                    <PropertyRef Name="IcaoCode" />
-                </Key>
-                <Property Name="IcaoCode" Type="Edm.String" Nullable="false">
-                    <Annotation Term="Org.OData.Core.V1.Permissions">
-                        <EnumMember>Org.OData.Core.V1.Permission/Read</EnumMember>
-                    </Annotation>
-                </Property>
-                <Property Name="Name" Type="Edm.String" Nullable="false" />
-                <Property Name="IataCode" Type="Edm.String" Nullable="false">
-                    <Annotation Term="Org.OData.Core.V1.Immutable" Bool="true" />
-                </Property>
-                <Property Name="Location" Type="Microsoft.OData.SampleService.Models.TripPin.AirportLocation" Nullable="false" />
-            </EntityType>
-            <EntityType Name="PlanItem">
-                <Key>
-                    <PropertyRef Name="PlanItemId" />
-                </Key>
-                <Property Name="PlanItemId" Type="Edm.Int32" Nullable="false">
-                    <Annotation Term="Org.OData.Core.V1.Permissions">
-                        <EnumMember>Org.OData.Core.V1.Permission/Read</EnumMember>
-                    </Annotation>
-                </Property>
-                <Property Name="ConfirmationCode" Type="Edm.String" />
-                <Property Name="StartsAt" Type="Edm.DateTimeOffset" />
-                <Property Name="EndsAt" Type="Edm.DateTimeOffset" />
-                <Property Name="Duration" Type="Edm.Duration" />
-            </EntityType>
-            <EntityType Name="PublicTransportation" BaseType="Microsoft.OData.SampleService.Models.TripPin.PlanItem">
-                <Property Name="SeatNumber" Type="Edm.String" />
-            </EntityType>
-            <EntityType Name="Flight" BaseType="Microsoft.OData.SampleService.Models.TripPin.PublicTransportation">
-                <Property Name="FlightNumber" Type="Edm.String" Nullable="false" />
-                <NavigationProperty Name="From" Type="Microsoft.OData.SampleService.Models.TripPin.Airport" Nullable="false" />
-                <NavigationProperty Name="To" Type="Microsoft.OData.SampleService.Models.TripPin.Airport" Nullable="false" />
-                <NavigationProperty Name="Airline" Type="Microsoft.OData.SampleService.Models.TripPin.Airline" Nullable="false" />
-            </EntityType>
-            <EntityType Name="Event" BaseType="Microsoft.OData.SampleService.Models.TripPin.PlanItem" OpenType="true">
-                <Property Name="Description" Type="Edm.String" />
-                <Property Name="OccursAt" Type="Microsoft.OData.SampleService.Models.TripPin.EventLocation" Nullable="false" />
-            </EntityType>
-            <EntityType Name="Trip">
-                <Key>
-                    <PropertyRef Name="TripId" />
-                </Key>
-                <Property Name="TripId" Type="Edm.Int32" Nullable="false">
-                    <Annotation Term="Org.OData.Core.V1.Permissions">
-                        <EnumMember>Org.OData.Core.V1.Permission/Read</EnumMember>
-                    </Annotation>
-                </Property>
-                <Property Name="ShareId" Type="Edm.Guid" />
-                <Property Name="Description" Type="Edm.String" />
-                <Property Name="Name" Type="Edm.String" Nullable="false" />
-                <Property Name="Budget" Type="Edm.Single" Nullable="false">
-                    <Annotation Term="Org.OData.Measures.V1.ISOCurrency" String="USD" />
-                    <Annotation Term="Org.OData.Measures.V1.Scale" Int="2" />
-                </Property>
-                <Property Name="StartsAt" Type="Edm.DateTimeOffset" Nullable="false" />
-                <Property Name="EndsAt" Type="Edm.DateTimeOffset" Nullable="false" />
-                <Property Name="Tags" Type="Collection(Edm.String)" Nullable="false" />
-                <NavigationProperty Name="Photos" Type="Collection(Microsoft.OData.SampleService.Models.TripPin.Photo)" />
-                <NavigationProperty Name="PlanItems" Type="Collection(Microsoft.OData.SampleService.Models.TripPin.PlanItem)" ContainsTarget="true" />
-            </EntityType>
-            <Function Name="GetFavoriteAirline" IsBound="true" EntitySetPath="person/Trips/PlanItems/Microsoft.OData.SampleService.Models.TripPin.Flight/Airline" IsComposable="true">
-                <Parameter Name="person" Type="Microsoft.OData.SampleService.Models.TripPin.Person" Nullable="false" />
-                <ReturnType Type="Microsoft.OData.SampleService.Models.TripPin.Airline" Nullable="false" />
-            </Function>
-            <Function Name="GetInvolvedPeople" IsBound="true" IsComposable="true">
-                <Parameter Name="trip" Type="Microsoft.OData.SampleService.Models.TripPin.Trip" Nullable="false" />
-                <ReturnType Type="Collection(Microsoft.OData.SampleService.Models.TripPin.Person)" Nullable="false" />
-            </Function>
-            <Function Name="GetFriendsTrips" IsBound="true" EntitySetPath="person/Friends/Trips" IsComposable="true">
-                <Parameter Name="person" Type="Microsoft.OData.SampleService.Models.TripPin.Person" Nullable="false" />
-                <Parameter Name="userName" Type="Edm.String" Nullable="false" />
-                <ReturnType Type="Collection(Microsoft.OData.SampleService.Models.TripPin.Trip)" Nullable="false" />
-            </Function>
-            <Function Name="GetNearestAirport" IsComposable="true">
-                <Parameter Name="lat" Type="Edm.Double" Nullable="false" />
-                <Parameter Name="lon" Type="Edm.Double" Nullable="false" />
-                <ReturnType Type="Microsoft.OData.SampleService.Models.TripPin.Airport" Nullable="false" />
-            </Function>
-            <Action Name="ResetDataSource" />
-            <Action Name="ShareTrip" IsBound="true">
-                <Parameter Name="person" Type="Microsoft.OData.SampleService.Models.TripPin.Person" Nullable="false" />
-                <Parameter Name="userName" Type="Edm.String" Nullable="false" />
-                <Parameter Name="tripId" Type="Edm.Int32" Nullable="false" />
-            </Action>
-            <EntityContainer Name="DefaultContainer">
-                <EntitySet Name="Photos" EntityType="Microsoft.OData.SampleService.Models.TripPin.Photo">
-                    <Annotation Term="Org.OData.Core.V1.ResourcePath" String="Photos" />
-                    <Annotation Term="Org.OData.Capabilities.V1.SearchRestrictions">
-                        <Record>
-                            <PropertyValue Property="Searchable" Bool="true" />
-                            <PropertyValue Property="UnsupportedExpressions">
-                                <EnumMember>Org.OData.Capabilities.V1.SearchExpressions/none</EnumMember>
-                            </PropertyValue>
-                        </Record>
-                    </Annotation>
-                    <Annotation Term="Org.OData.Capabilities.V1.InsertRestrictions">
-                        <Record>
-                            <PropertyValue Property="Insertable" Bool="true" />
-                            <PropertyValue Property="NonInsertableNavigationProperties">
-                                <Collection />
-                            </PropertyValue>
-                        </Record>
-                    </Annotation>
-                </EntitySet>
-                <EntitySet Name="People" EntityType="Microsoft.OData.SampleService.Models.TripPin.Person">
-                    <NavigationPropertyBinding Path="Friends" Target="People" />
-                    <NavigationPropertyBinding Path="Microsoft.OData.SampleService.Models.TripPin.Flight/Airline" Target="Airlines" />
-                    <NavigationPropertyBinding Path="Microsoft.OData.SampleService.Models.TripPin.Flight/From" Target="Airports" />
-                    <NavigationPropertyBinding Path="Microsoft.OData.SampleService.Models.TripPin.Flight/To" Target="Airports" />
-                    <NavigationPropertyBinding Path="Photo" Target="Photos" />
-                    <NavigationPropertyBinding Path="Microsoft.OData.SampleService.Models.TripPin.Trip/Photos" Target="Photos" />
-                    <Annotation Term="Org.OData.Core.V1.OptimisticConcurrency">
-                        <Collection>
-                            <PropertyPath>Concurrency</PropertyPath>
-                        </Collection>
-                    </Annotation>
-                    <Annotation Term="Org.OData.Core.V1.ResourcePath" String="People" />
-                    <Annotation Term="Org.OData.Capabilities.V1.NavigationRestrictions">
-                        <Record>
-                            <PropertyValue Property="Navigability">
-                                <EnumMember>Org.OData.Capabilities.V1.NavigationType/None</EnumMember>
-                            </PropertyValue>
-                            <PropertyValue Property="RestrictedProperties">
-                                <Collection>
-                                    <Record>
-                                        <PropertyValue Property="NavigationProperty" NavigationPropertyPath="Friends" />
-                                        <PropertyValue Property="Navigability">
-                                            <EnumMember>Org.OData.Capabilities.V1.NavigationType/Recursive</EnumMember>
-                                        </PropertyValue>
-                                    </Record>
-                                </Collection>
-                            </PropertyValue>
-                        </Record>
-                    </Annotation>
-                    <Annotation Term="Org.OData.Capabilities.V1.SearchRestrictions">
-                        <Record>
-                            <PropertyValue Property="Searchable" Bool="true" />
-                            <PropertyValue Property="UnsupportedExpressions">
-                                <EnumMember>Org.OData.Capabilities.V1.SearchExpressions/none</EnumMember>
-                            </PropertyValue>
-                        </Record>
-                    </Annotation>
-                    <Annotation Term="Org.OData.Capabilities.V1.InsertRestrictions">
-                        <Record>
-                            <PropertyValue Property="Insertable" Bool="true" />
-                            <PropertyValue Property="NonInsertableNavigationProperties">
-                                <Collection>
-                                    <NavigationPropertyPath>Trips</NavigationPropertyPath>
-                                    <NavigationPropertyPath>Friends</NavigationPropertyPath>
-                                </Collection>
-                            </PropertyValue>
-                        </Record>
-                    </Annotation>
-                </EntitySet>
-                <EntitySet Name="Airlines" EntityType="Microsoft.OData.SampleService.Models.TripPin.Airline">
-                    <Annotation Term="Org.OData.Core.V1.ResourcePath" String="Airlines" />
-                    <Annotation Term="Org.OData.Capabilities.V1.SearchRestrictions">
-                        <Record>
-                            <PropertyValue Property="Searchable" Bool="true" />
-                            <PropertyValue Property="UnsupportedExpressions">
-                                <EnumMember>Org.OData.Capabilities.V1.SearchExpressions/none</EnumMember>
-                            </PropertyValue>
-                        </Record>
-                    </Annotation>
-                    <Annotation Term="Org.OData.Capabilities.V1.InsertRestrictions">
-                        <Record>
-                            <PropertyValue Property="Insertable" Bool="true" />
-                            <PropertyValue Property="NonInsertableNavigationProperties">
-                                <Collection />
-                            </PropertyValue>
-                        </Record>
-                    </Annotation>
-                </EntitySet>
-                <EntitySet Name="Airports" EntityType="Microsoft.OData.SampleService.Models.TripPin.Airport">
-                    <Annotation Term="Org.OData.Core.V1.ResourcePath" String="Airports" />
-                    <Annotation Term="Org.OData.Capabilities.V1.SearchRestrictions">
-                        <Record>
-                            <PropertyValue Property="Searchable" Bool="true" />
-                            <PropertyValue Property="UnsupportedExpressions">
-                                <EnumMember>Org.OData.Capabilities.V1.SearchExpressions/none</EnumMember>
-                            </PropertyValue>
-                        </Record>
-                    </Annotation>
-                    <Annotation Term="Org.OData.Capabilities.V1.InsertRestrictions">
-                        <Record>
-                            <PropertyValue Property="Insertable" Bool="false" />
-                            <PropertyValue Property="NonInsertableNavigationProperties">
-                                <Collection />
-                            </PropertyValue>
-                        </Record>
-                    </Annotation>
-                    <Annotation Term="Org.OData.Capabilities.V1.DeleteRestrictions">
-                        <Record>
-                            <PropertyValue Property="Deletable" Bool="false" />
-                            <PropertyValue Property="NonDeletableNavigationProperties">
-                                <Collection />
-                            </PropertyValue>
-                        </Record>
-                    </Annotation>
-                </EntitySet>
-                <Singleton Name="Me" Type="Microsoft.OData.SampleService.Models.TripPin.Person">
-                    <NavigationPropertyBinding Path="Friends" Target="People" />
-                    <NavigationPropertyBinding Path="Microsoft.OData.SampleService.Models.TripPin.Flight/Airline" Target="Airlines" />
-                    <NavigationPropertyBinding Path="Microsoft.OData.SampleService.Models.TripPin.Flight/From" Target="Airports" />
-                    <NavigationPropertyBinding Path="Microsoft.OData.SampleService.Models.TripPin.Flight/To" Target="Airports" />
-                    <NavigationPropertyBinding Path="Photo" Target="Photos" />
-                    <NavigationPropertyBinding Path="Microsoft.OData.SampleService.Models.TripPin.Trip/Photos" Target="Photos" />
-                    <Annotation Term="Org.OData.Core.V1.ResourcePath" String="Me" />
-                </Singleton>
-                <FunctionImport Name="GetNearestAirport" Function="Microsoft.OData.SampleService.Models.TripPin.GetNearestAirport" EntitySet="Airports" IncludeInServiceDocument="true">
-                    <Annotation Term="Org.OData.Core.V1.ResourcePath" String="Microsoft.OData.SampleService.Models.TripPin.GetNearestAirport" />
-                </FunctionImport>
-                <ActionImport Name="ResetDataSource" Action="Microsoft.OData.SampleService.Models.TripPin.ResetDataSource" />
-                <Annotation Term="Org.OData.Core.V1.Description" String="TripPin service is a sample service for OData V4." />
-            </EntityContainer>
-            <Annotations Target="Microsoft.OData.SampleService.Models.TripPin.DefaultContainer">
-                <Annotation Term="Org.OData.Core.V1.DereferenceableIDs" Bool="true" />
-                <Annotation Term="Org.OData.Core.V1.ConventionalIDs" Bool="true" />
-                <Annotation Term="Org.OData.Capabilities.V1.ConformanceLevel">
-                    <EnumMember>Org.OData.Capabilities.V1.ConformanceLevelType/Advanced</EnumMember>
-                </Annotation>
-                <Annotation Term="Org.OData.Capabilities.V1.SupportedFormats">
-                    <Collection>
-                        <String>application/json;odata.metadata=full;IEEE754Compatible=false;odata.streaming=true</String>
-                        <String>application/json;odata.metadata=minimal;IEEE754Compatible=false;odata.streaming=true</String>
-                        <String>application/json;odata.metadata=none;IEEE754Compatible=false;odata.streaming=true</String>
-                    </Collection>
-                </Annotation>
-                <Annotation Term="Org.OData.Capabilities.V1.AsynchronousRequestsSupported" Bool="true" />
-                <Annotation Term="Org.OData.Capabilities.V1.BatchContinueOnErrorSupported" Bool="false" />
-                <Annotation Term="Org.OData.Capabilities.V1.FilterFunctions">
-                    <Collection>
-                        <String>contains</String>
-                        <String>endswith</String>
-                        <String>startswith</String>
-                        <String>length</String>
-                        <String>indexof</String>
-                        <String>substring</String>
-                        <String>tolower</String>
-                        <String>toupper</String>
-                        <String>trim</String>
-                        <String>concat</String>
-                        <String>year</String>
-                        <String>month</String>
-                        <String>day</String>
-                        <String>hour</String>
-                        <String>minute</String>
-                        <String>second</String>
-                        <String>round</String>
-                        <String>floor</String>
-                        <String>ceiling</String>
-                        <String>cast</String>
-                        <String>isof</String>
-                    </Collection>
-                </Annotation>
-            </Annotations>
-        </Schema>
-    </edmx:DataServices>
+	<edmx:DataServices>
+		<Schema Namespace="Microsoft.OData.SampleService.Models.TripPin"
+			xmlns="http://docs.oasis-open.org/odata/ns/edm">
+			<EnumType Name="PersonGender">
+				<Member Name="Male" Value="0" />
+				<Member Name="Female" Value="1" />
+				<Member Name="Unknown" Value="2" />
+			</EnumType>
+			<ComplexType Name="City">
+				<Property Name="CountryRegion" Type="Edm.String" Nullable="false" />
+				<Property Name="Name" Type="Edm.String" Nullable="false" />
+				<Property Name="Region" Type="Edm.String" Nullable="false" />
+			</ComplexType>
+			<ComplexType Name="Location" OpenType="true">
+				<Property Name="Address" Type="Edm.String" Nullable="false" />
+				<Property Name="City"
+					Type="Microsoft.OData.SampleService.Models.TripPin.City" Nullable="false" />
+			</ComplexType>
+			<ComplexType Name="EventLocation"
+				BaseType="Microsoft.OData.SampleService.Models.TripPin.Location"
+				OpenType="true">
+				<Property Name="BuildingInfo" Type="Edm.String" />
+			</ComplexType>
+			<ComplexType Name="AirportLocation"
+				BaseType="Microsoft.OData.SampleService.Models.TripPin.Location"
+				OpenType="true">
+				<Property Name="Loc" Type="Edm.GeographyPoint" Nullable="false"
+					SRID="4326" />
+			</ComplexType>
+			<EntityType Name="Photo" HasStream="true">
+				<Key>
+					<PropertyRef Name="Id" />
+				</Key>
+				<Property Name="Id" Type="Edm.Int64" Nullable="false">
+					<Annotation Term="Org.OData.Core.V1.Permissions">
+						<EnumMember>Org.OData.Core.V1.Permission/Read</EnumMember>
+					</Annotation>
+				</Property>
+				<Property Name="Name" Type="Edm.String" />
+				<Annotation Term="Org.OData.Core.V1.AcceptableMediaTypes">
+					<Collection>
+						<String>image/jpeg</String>
+					</Collection>
+				</Annotation>
+			</EntityType>
+			<EntityType Name="Person" OpenType="true">
+				<Key>
+					<PropertyRef Name="UserName" />
+				</Key>
+				<Property Name="UserName" Type="Edm.String" Nullable="false">
+					<Annotation Term="Org.OData.Core.V1.Permissions">
+						<EnumMember>Org.OData.Core.V1.Permission/Read</EnumMember>
+					</Annotation>
+				</Property>
+				<Property Name="FirstName" Type="Edm.String" Nullable="true" />
+				<Property Name="LastName" Type="Edm.String" Nullable="false" />
+				<Property Name="Emails" Type="Collection(Edm.String)" />
+				<Property Name="AddressInfo"
+					Type="Collection(Microsoft.OData.SampleService.Models.TripPin.Location)" />
+				<Property Name="Gender"
+					Type="Microsoft.OData.SampleService.Models.TripPin.PersonGender" />
+				<Property Name="Concurrency" Type="Edm.Int64" Nullable="false">
+					<Annotation Term="Org.OData.Core.V1.Computed" Bool="true" />
+				</Property>
+				<NavigationProperty Name="Friends"
+					Type="Collection(Microsoft.OData.SampleService.Models.TripPin.Person)" />
+				<NavigationProperty Name="Trips"
+					Type="Collection(Microsoft.OData.SampleService.Models.TripPin.Trip)"
+					ContainsTarget="true" />
+				<NavigationProperty Name="Photo"
+					Type="Microsoft.OData.SampleService.Models.TripPin.Photo" />
+			</EntityType>
+			<EntityType Name="Airline">
+				<Key>
+					<PropertyRef Name="AirlineCode" />
+				</Key>
+				<Property Name="AirlineCode" Type="Edm.String" Nullable="false">
+					<Annotation Term="Org.OData.Core.V1.Permissions">
+						<EnumMember>Org.OData.Core.V1.Permission/Read</EnumMember>
+					</Annotation>
+				</Property>
+				<Property Name="Name" Type="Edm.String" Nullable="false" />
+				<Property Name="Picture" Type="Edm.Stream" Nullable="true" />
+			</EntityType>
+			<EntityType Name="Airport">
+				<Key>
+					<PropertyRef Name="IcaoCode" />
+				</Key>
+				<Property Name="IcaoCode" Type="Edm.String" Nullable="false">
+					<Annotation Term="Org.OData.Core.V1.Permissions">
+						<EnumMember>Org.OData.Core.V1.Permission/Read</EnumMember>
+					</Annotation>
+				</Property>
+				<Property Name="Name" Type="Edm.String" Nullable="false" />
+				<Property Name="IataCode" Type="Edm.String" Nullable="false">
+					<Annotation Term="Org.OData.Core.V1.Immutable" Bool="true" />
+				</Property>
+				<Property Name="Location"
+					Type="Microsoft.OData.SampleService.Models.TripPin.AirportLocation"
+					Nullable="false" />
+			</EntityType>
+			<EntityType Name="PlanItem">
+				<Key>
+					<PropertyRef Name="PlanItemId" />
+				</Key>
+				<Property Name="PlanItemId" Type="Edm.Int32" Nullable="false">
+					<Annotation Term="Org.OData.Core.V1.Permissions">
+						<EnumMember>Org.OData.Core.V1.Permission/Read</EnumMember>
+					</Annotation>
+				</Property>
+				<Property Name="ConfirmationCode" Type="Edm.String" />
+				<Property Name="StartsAt" Type="Edm.DateTimeOffset" />
+				<Property Name="EndsAt" Type="Edm.DateTimeOffset" />
+				<Property Name="Duration" Type="Edm.Duration" />
+			</EntityType>
+			<EntityType Name="PublicTransportation"
+				BaseType="Microsoft.OData.SampleService.Models.TripPin.PlanItem">
+				<Property Name="SeatNumber" Type="Edm.String" />
+			</EntityType>
+			<EntityType Name="Flight"
+				BaseType="Microsoft.OData.SampleService.Models.TripPin.PublicTransportation">
+				<Property Name="FlightNumber" Type="Edm.String" Nullable="false" />
+				<NavigationProperty Name="From"
+					Type="Microsoft.OData.SampleService.Models.TripPin.Airport"
+					Nullable="false" />
+				<NavigationProperty Name="To"
+					Type="Microsoft.OData.SampleService.Models.TripPin.Airport"
+					Nullable="false" />
+				<NavigationProperty Name="Airline"
+					Type="Microsoft.OData.SampleService.Models.TripPin.Airline"
+					Nullable="false" />
+			</EntityType>
+			<EntityType Name="Event"
+				BaseType="Microsoft.OData.SampleService.Models.TripPin.PlanItem"
+				OpenType="true">
+				<Property Name="Description" Type="Edm.String" />
+				<Property Name="OccursAt"
+					Type="Microsoft.OData.SampleService.Models.TripPin.EventLocation"
+					Nullable="false" />
+			</EntityType>
+			<EntityType Name="Trip">
+				<Key>
+					<PropertyRef Name="TripId" />
+				</Key>
+				<Property Name="TripId" Type="Edm.Int32" Nullable="false">
+					<Annotation Term="Org.OData.Core.V1.Permissions">
+						<EnumMember>Org.OData.Core.V1.Permission/Read</EnumMember>
+					</Annotation>
+				</Property>
+				<Property Name="ShareId" Type="Edm.Guid" />
+				<Property Name="Description" Type="Edm.String" />
+				<Property Name="Name" Type="Edm.String" Nullable="false" />
+				<Property Name="Budget" Type="Edm.Single" Nullable="false">
+					<Annotation Term="Org.OData.Measures.V1.ISOCurrency"
+						String="USD" />
+					<Annotation Term="Org.OData.Measures.V1.Scale" Int="2" />
+				</Property>
+				<Property Name="StartsAt" Type="Edm.DateTimeOffset"
+					Nullable="false" />
+				<Property Name="EndsAt" Type="Edm.DateTimeOffset" Nullable="false" />
+				<Property Name="Tags" Type="Collection(Edm.String)"
+					Nullable="false" />
+				<NavigationProperty Name="Photos"
+					Type="Collection(Microsoft.OData.SampleService.Models.TripPin.Photo)" />
+				<NavigationProperty Name="PlanItems"
+					Type="Collection(Microsoft.OData.SampleService.Models.TripPin.PlanItem)"
+					ContainsTarget="true" />
+			</EntityType>
+			<Function Name="GetFavoriteAirline" IsBound="true"
+				EntitySetPath="person/Trips/PlanItems/Microsoft.OData.SampleService.Models.TripPin.Flight/Airline"
+				IsComposable="true">
+				<Parameter Name="person"
+					Type="Microsoft.OData.SampleService.Models.TripPin.Person"
+					Nullable="false" />
+				<ReturnType Type="Microsoft.OData.SampleService.Models.TripPin.Airline"
+					Nullable="false" />
+			</Function>
+			<Function Name="GetInvolvedPeople" IsBound="true"
+				IsComposable="true">
+				<Parameter Name="trip"
+					Type="Microsoft.OData.SampleService.Models.TripPin.Trip" Nullable="false" />
+				<ReturnType
+					Type="Collection(Microsoft.OData.SampleService.Models.TripPin.Person)"
+					Nullable="false" />
+			</Function>
+			<Function Name="GetFriendsTrips" IsBound="true"
+				EntitySetPath="person/Friends/Trips" IsComposable="true">
+				<Parameter Name="person"
+					Type="Microsoft.OData.SampleService.Models.TripPin.Person"
+					Nullable="false" />
+				<Parameter Name="userName" Type="Edm.String" Nullable="false" />
+				<ReturnType
+					Type="Collection(Microsoft.OData.SampleService.Models.TripPin.Trip)"
+					Nullable="false" />
+			</Function>
+			<Function Name="GetNearestAirport" IsComposable="true">
+				<Parameter Name="lat" Type="Edm.Double" Nullable="false" />
+				<Parameter Name="lon" Type="Edm.Double" Nullable="false" />
+				<ReturnType Type="Microsoft.OData.SampleService.Models.TripPin.Airport"
+					Nullable="false" />
+			</Function>
+			<Action Name="ResetDataSource" />
+			<Action Name="ShareTrip" IsBound="true">
+				<Parameter Name="person"
+					Type="Microsoft.OData.SampleService.Models.TripPin.Person"
+					Nullable="false" />
+				<Parameter Name="userName" Type="Edm.String" Nullable="false" />
+				<Parameter Name="tripId" Type="Edm.Int32" Nullable="false" />
+			</Action>
+			<EntityContainer Name="DefaultContainer">
+				<EntitySet Name="Photos"
+					EntityType="Microsoft.OData.SampleService.Models.TripPin.Photo">
+					<Annotation Term="Org.OData.Core.V1.ResourcePath"
+						String="Photos" />
+					<Annotation Term="Org.OData.Capabilities.V1.SearchRestrictions">
+						<Record>
+							<PropertyValue Property="Searchable" Bool="true" />
+							<PropertyValue Property="UnsupportedExpressions">
+								<EnumMember>Org.OData.Capabilities.V1.SearchExpressions/none
+								</EnumMember>
+							</PropertyValue>
+						</Record>
+					</Annotation>
+					<Annotation Term="Org.OData.Capabilities.V1.InsertRestrictions">
+						<Record>
+							<PropertyValue Property="Insertable" Bool="true" />
+							<PropertyValue Property="NonInsertableNavigationProperties">
+								<Collection />
+							</PropertyValue>
+						</Record>
+					</Annotation>
+				</EntitySet>
+				<EntitySet Name="People"
+					EntityType="Microsoft.OData.SampleService.Models.TripPin.Person">
+					<NavigationPropertyBinding Path="Friends"
+						Target="People" />
+					<NavigationPropertyBinding
+						Path="Microsoft.OData.SampleService.Models.TripPin.Flight/Airline"
+						Target="Airlines" />
+					<NavigationPropertyBinding
+						Path="Microsoft.OData.SampleService.Models.TripPin.Flight/From"
+						Target="Airports" />
+					<NavigationPropertyBinding
+						Path="Microsoft.OData.SampleService.Models.TripPin.Flight/To"
+						Target="Airports" />
+					<NavigationPropertyBinding Path="Photo"
+						Target="Photos" />
+					<NavigationPropertyBinding
+						Path="Microsoft.OData.SampleService.Models.TripPin.Trip/Photos"
+						Target="Photos" />
+					<Annotation Term="Org.OData.Core.V1.OptimisticConcurrency">
+						<Collection>
+							<PropertyPath>Concurrency</PropertyPath>
+						</Collection>
+					</Annotation>
+					<Annotation Term="Org.OData.Core.V1.ResourcePath"
+						String="People" />
+					<Annotation Term="Org.OData.Capabilities.V1.NavigationRestrictions">
+						<Record>
+							<PropertyValue Property="Navigability">
+								<EnumMember>Org.OData.Capabilities.V1.NavigationType/None
+								</EnumMember>
+							</PropertyValue>
+							<PropertyValue Property="RestrictedProperties">
+								<Collection>
+									<Record>
+										<PropertyValue Property="NavigationProperty"
+											NavigationPropertyPath="Friends" />
+										<PropertyValue Property="Navigability">
+											<EnumMember>Org.OData.Capabilities.V1.NavigationType/Recursive
+											</EnumMember>
+										</PropertyValue>
+									</Record>
+								</Collection>
+							</PropertyValue>
+						</Record>
+					</Annotation>
+					<Annotation Term="Org.OData.Capabilities.V1.SearchRestrictions">
+						<Record>
+							<PropertyValue Property="Searchable" Bool="true" />
+							<PropertyValue Property="UnsupportedExpressions">
+								<EnumMember>Org.OData.Capabilities.V1.SearchExpressions/none
+								</EnumMember>
+							</PropertyValue>
+						</Record>
+					</Annotation>
+					<Annotation Term="Org.OData.Capabilities.V1.InsertRestrictions">
+						<Record>
+							<PropertyValue Property="Insertable" Bool="true" />
+							<PropertyValue Property="NonInsertableNavigationProperties">
+								<Collection>
+									<NavigationPropertyPath>Trips</NavigationPropertyPath>
+									<NavigationPropertyPath>Friends</NavigationPropertyPath>
+								</Collection>
+							</PropertyValue>
+						</Record>
+					</Annotation>
+				</EntitySet>
+				<EntitySet Name="Airlines"
+					EntityType="Microsoft.OData.SampleService.Models.TripPin.Airline">
+					<Annotation Term="Org.OData.Core.V1.ResourcePath"
+						String="Airlines" />
+					<Annotation Term="Org.OData.Capabilities.V1.SearchRestrictions">
+						<Record>
+							<PropertyValue Property="Searchable" Bool="true" />
+							<PropertyValue Property="UnsupportedExpressions">
+								<EnumMember>Org.OData.Capabilities.V1.SearchExpressions/none
+								</EnumMember>
+							</PropertyValue>
+						</Record>
+					</Annotation>
+					<Annotation Term="Org.OData.Capabilities.V1.InsertRestrictions">
+						<Record>
+							<PropertyValue Property="Insertable" Bool="true" />
+							<PropertyValue Property="NonInsertableNavigationProperties">
+								<Collection />
+							</PropertyValue>
+						</Record>
+					</Annotation>
+				</EntitySet>
+				<EntitySet Name="Airports"
+					EntityType="Microsoft.OData.SampleService.Models.TripPin.Airport">
+					<Annotation Term="Org.OData.Core.V1.ResourcePath"
+						String="Airports" />
+					<Annotation Term="Org.OData.Capabilities.V1.SearchRestrictions">
+						<Record>
+							<PropertyValue Property="Searchable" Bool="true" />
+							<PropertyValue Property="UnsupportedExpressions">
+								<EnumMember>Org.OData.Capabilities.V1.SearchExpressions/none
+								</EnumMember>
+							</PropertyValue>
+						</Record>
+					</Annotation>
+					<Annotation Term="Org.OData.Capabilities.V1.InsertRestrictions">
+						<Record>
+							<PropertyValue Property="Insertable" Bool="false" />
+							<PropertyValue Property="NonInsertableNavigationProperties">
+								<Collection />
+							</PropertyValue>
+						</Record>
+					</Annotation>
+					<Annotation Term="Org.OData.Capabilities.V1.DeleteRestrictions">
+						<Record>
+							<PropertyValue Property="Deletable" Bool="false" />
+							<PropertyValue Property="NonDeletableNavigationProperties">
+								<Collection />
+							</PropertyValue>
+						</Record>
+					</Annotation>
+				</EntitySet>
+				<Singleton Name="Me"
+					Type="Microsoft.OData.SampleService.Models.TripPin.Person">
+					<NavigationPropertyBinding Path="Friends"
+						Target="People" />
+					<NavigationPropertyBinding
+						Path="Microsoft.OData.SampleService.Models.TripPin.Flight/Airline"
+						Target="Airlines" />
+					<NavigationPropertyBinding
+						Path="Microsoft.OData.SampleService.Models.TripPin.Flight/From"
+						Target="Airports" />
+					<NavigationPropertyBinding
+						Path="Microsoft.OData.SampleService.Models.TripPin.Flight/To"
+						Target="Airports" />
+					<NavigationPropertyBinding Path="Photo"
+						Target="Photos" />
+					<NavigationPropertyBinding
+						Path="Microsoft.OData.SampleService.Models.TripPin.Trip/Photos"
+						Target="Photos" />
+					<Annotation Term="Org.OData.Core.V1.ResourcePath"
+						String="Me" />
+				</Singleton>
+				<FunctionImport Name="GetNearestAirport"
+					Function="Microsoft.OData.SampleService.Models.TripPin.GetNearestAirport"
+					EntitySet="Airports" IncludeInServiceDocument="true">
+					<Annotation Term="Org.OData.Core.V1.ResourcePath"
+						String="Microsoft.OData.SampleService.Models.TripPin.GetNearestAirport" />
+				</FunctionImport>
+				<ActionImport Name="ResetDataSource"
+					Action="Microsoft.OData.SampleService.Models.TripPin.ResetDataSource" />
+				<Annotation Term="Org.OData.Core.V1.Description"
+					String="TripPin service is a sample service for OData V4." />
+			</EntityContainer>
+			<Annotations
+				Target="Microsoft.OData.SampleService.Models.TripPin.DefaultContainer">
+				<Annotation Term="Org.OData.Core.V1.DereferenceableIDs"
+					Bool="true" />
+				<Annotation Term="Org.OData.Core.V1.ConventionalIDs"
+					Bool="true" />
+				<Annotation Term="Org.OData.Capabilities.V1.ConformanceLevel">
+					<EnumMember>Org.OData.Capabilities.V1.ConformanceLevelType/Advanced
+					</EnumMember>
+				</Annotation>
+				<Annotation Term="Org.OData.Capabilities.V1.SupportedFormats">
+					<Collection>
+						<String>application/json;odata.metadata=full;IEEE754Compatible=false;odata.streaming=true
+						</String>
+						<String>application/json;odata.metadata=minimal;IEEE754Compatible=false;odata.streaming=true
+						</String>
+						<String>application/json;odata.metadata=none;IEEE754Compatible=false;odata.streaming=true
+						</String>
+					</Collection>
+				</Annotation>
+				<Annotation
+					Term="Org.OData.Capabilities.V1.AsynchronousRequestsSupported"
+					Bool="true" />
+				<Annotation
+					Term="Org.OData.Capabilities.V1.BatchContinueOnErrorSupported"
+					Bool="false" />
+				<Annotation Term="Org.OData.Capabilities.V1.FilterFunctions">
+					<Collection>
+						<String>contains</String>
+						<String>endswith</String>
+						<String>startswith</String>
+						<String>length</String>
+						<String>indexof</String>
+						<String>substring</String>
+						<String>tolower</String>
+						<String>toupper</String>
+						<String>trim</String>
+						<String>concat</String>
+						<String>year</String>
+						<String>month</String>
+						<String>day</String>
+						<String>hour</String>
+						<String>minute</String>
+						<String>second</String>
+						<String>round</String>
+						<String>floor</String>
+						<String>ceiling</String>
+						<String>cast</String>
+						<String>isof</String>
+					</Collection>
+				</Annotation>
+			</Annotations>
+			<Term Name="IsURI" Type="Core.Tag" DefaultValue="true"
+				AppliesTo="Property">
+				<Annotation Term="Core.Description">
+					<String>
+						Properties and terms annotated with this term MUST contain a valid URI
+					</String>
+				</Annotation>
+				<Annotation Term="Core.RequiresType" String="Edm.String" />
+			</Term>
+		</Schema>
+	</edmx:DataServices>
 </edmx:Edmx>
\ No newline at end of file


[09/22] olingo-odata4 git commit: [OLINGO-852] less warnings + general clean-up

Posted by mi...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/fit/src/main/java/org/apache/olingo/fit/AbstractServices.java
----------------------------------------------------------------------
diff --git a/fit/src/main/java/org/apache/olingo/fit/AbstractServices.java b/fit/src/main/java/org/apache/olingo/fit/AbstractServices.java
deleted file mode 100644
index c287e5b..0000000
--- a/fit/src/main/java/org/apache/olingo/fit/AbstractServices.java
+++ /dev/null
@@ -1,1947 +0,0 @@
-/*
- * 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;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStreamWriter;
-import java.net.URI;
-import java.util.AbstractMap;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.ConcurrentModificationException;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.UUID;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import javax.mail.Header;
-import javax.mail.internet.MimeBodyPart;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.DELETE;
-import javax.ws.rs.DefaultValue;
-import javax.ws.rs.GET;
-import javax.ws.rs.HeaderParam;
-import javax.ws.rs.NotFoundException;
-import javax.ws.rs.POST;
-import javax.ws.rs.PUT;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.QueryParam;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.MultivaluedHashMap;
-import javax.ws.rs.core.MultivaluedMap;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.UriInfo;
-
-import org.apache.commons.io.IOUtils;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.commons.lang3.tuple.Pair;
-import org.apache.cxf.jaxrs.client.WebClient;
-import org.apache.cxf.jaxrs.ext.multipart.Attachment;
-import org.apache.cxf.jaxrs.ext.multipart.Multipart;
-import org.apache.cxf.jaxrs.ext.multipart.MultipartBody;
-import org.apache.olingo.client.api.data.ResWrap;
-import org.apache.olingo.client.api.serialization.ODataDeserializer;
-import org.apache.olingo.client.api.serialization.ODataSerializer;
-import org.apache.olingo.client.core.serialization.AtomSerializer;
-import org.apache.olingo.client.core.serialization.JsonDeserializer;
-import org.apache.olingo.client.core.serialization.JsonSerializer;
-import org.apache.olingo.commons.api.data.ComplexValue;
-import org.apache.olingo.commons.api.data.Entity;
-import org.apache.olingo.commons.api.data.EntityCollection;
-import org.apache.olingo.commons.api.data.Link;
-import org.apache.olingo.commons.api.data.Property;
-import org.apache.olingo.commons.api.data.ValueType;
-import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
-import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
-import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion;
-import org.apache.olingo.commons.api.format.ContentType;
-import org.apache.olingo.commons.core.edm.primitivetype.EdmPrimitiveTypeFactory;
-import org.apache.olingo.fit.metadata.EntityType;
-import org.apache.olingo.fit.metadata.Metadata;
-import org.apache.olingo.fit.metadata.NavigationProperty;
-import org.apache.olingo.fit.methods.PATCH;
-import org.apache.olingo.fit.serializer.FITAtomDeserializer;
-import org.apache.olingo.fit.utils.AbstractUtilities;
-import org.apache.olingo.fit.utils.Accept;
-import org.apache.olingo.fit.utils.Commons;
-import org.apache.olingo.fit.utils.ConstantKey;
-import org.apache.olingo.fit.utils.Constants;
-import org.apache.olingo.fit.utils.FSManager;
-import org.apache.olingo.fit.utils.JSONUtilities;
-import org.apache.olingo.fit.utils.LinkInfo;
-import org.apache.olingo.fit.utils.XMLUtilities;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-
-public abstract class AbstractServices {
-
-  /**
-   * Logger.
-   */
-  protected static final Logger LOG = LoggerFactory.getLogger(AbstractServices.class);
-
-  private static final Pattern REQUEST_PATTERN = Pattern.compile("(.*) (http://.*) HTTP/.*");
-
-  private static final Pattern BATCH_REQUEST_REF_PATTERN = Pattern.compile("(.*) ([$]\\d+)(.*) HTTP/.*");
-
-  private static final Pattern REF_PATTERN = Pattern.compile("([$]\\d+)");
-
-  protected static final String BOUNDARY = "batch_243234_25424_ef_892u748";
-
-  protected static final String MULTIPART_MIXED = "multipart/mixed";
-
-  protected static final String APPLICATION_OCTET_STREAM = "application/octet-stream";
-
-  protected final ODataServiceVersion version;
-
-  protected final Metadata metadata;
-
-  protected final ODataDeserializer atomDeserializer;
-
-  protected final ODataDeserializer jsonDeserializer;
-
-  protected final ODataSerializer atomSerializer;
-
-  protected final ODataSerializer jsonSerializer;
-
-  protected final XMLUtilities xml;
-
-  protected final JSONUtilities json;
-
-  public AbstractServices(final ODataServiceVersion version, final Metadata metadata) throws IOException {
-    this.version = version;
-    this.metadata = metadata;
-
-    atomDeserializer = new FITAtomDeserializer();
-    jsonDeserializer = new JsonDeserializer(true);
-    atomSerializer = new AtomSerializer(true);
-    jsonSerializer = new JsonSerializer(true, ContentType.JSON_FULL_METADATA);
-
-    xml = new XMLUtilities(metadata);
-    json = new JSONUtilities(metadata);
-  }
-
-  /**
-   * Provide sample services.
-   *
-   * @param accept Accept header.
-   * @return OData services.
-   */
-  @GET
-  public Response getSevices(@HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept) {
-    try {
-      final Accept acceptType = Accept.parse(accept);
-
-      if (acceptType == Accept.ATOM) {
-        throw new UnsupportedMediaTypeException("Unsupported media type");
-      }
-
-      return xml.createResponse(
-          null,
-          FSManager.instance(version).readFile(Constants.get(ConstantKey.SERVICES), acceptType),
-          null, acceptType);
-    } catch (Exception e) {
-      return xml.createFaultResponse(accept, e);
-    }
-  }
-
-  /**
-   * Provide sample getMetadata().
-   *
-   * @return getMetadata().
-   */
-  @GET
-  @Path("/$metadata")
-  @Produces(MediaType.APPLICATION_XML)
-  public Response getMetadata() {
-    return getMetadata(Constants.get(ConstantKey.METADATA));
-  }
-
-  protected Response getMetadata(final String filename) {
-    try {
-      return xml.createResponse(null, FSManager.instance(version).readRes(filename, Accept.XML), null, Accept.XML);
-    } catch (Exception e) {
-      return xml.createFaultResponse(Accept.XML.toString(), e);
-    }
-  }
-
-  @POST
-  @Path("/$batch")
-  @Consumes(MULTIPART_MIXED)
-  @Produces(APPLICATION_OCTET_STREAM + ";boundary=" + BOUNDARY)
-  public Response batch(
-      @HeaderParam("Authorization") @DefaultValue(StringUtils.EMPTY) final String authorization,
-      @HeaderParam("Prefer") @DefaultValue(StringUtils.EMPTY) final String prefer,
-      final @Multipart MultipartBody attachment) {
-    try {
-      final boolean continueOnError = prefer.contains("odata.continue-on-error");
-      return xml.createBatchResponse(
-          exploreMultipart(attachment.getAllAttachments(), BOUNDARY, continueOnError));
-    } catch (IOException e) {
-      return xml.createFaultResponse(Accept.XML.toString(), e);
-    }
-  }
-
-  // ----------------------------------------------
-  // just for non nullable property test into PropertyTestITCase
-  // ----------------------------------------------
-  @PATCH
-  @Path("/Driver('2')")
-  public Response patchDriver() {
-    return xml.createFaultResponse(Accept.JSON_FULLMETA.toString(), new Exception("Non nullable properties"));
-  }
-
-  @GET
-  @Path("/StoredPIs(1000)")
-  public Response getStoredPI(@Context final UriInfo uriInfo) {
-    final Entity entity = new Entity();
-    entity.setType("Microsoft.Test.OData.Services.ODataWCFService.StoredPI");
-    final Property id = new Property();
-    id.setType("Edm.Int32");
-    id.setName("StoredPIID");
-    id.setValue(ValueType.PRIMITIVE, 1000);
-    entity.getProperties().add(id);
-    final Link edit = new Link();
-    edit.setHref(uriInfo.getRequestUri().toASCIIString());
-    edit.setRel("edit");
-    edit.setTitle("StoredPI");
-    entity.setEditLink(edit);
-
-    final ByteArrayOutputStream content = new ByteArrayOutputStream();
-    final OutputStreamWriter writer = new OutputStreamWriter(content, Constants.ENCODING);
-    try {
-      jsonSerializer.write(writer, new ResWrap<Entity>((URI) null, null, entity));
-      return xml.createResponse(new ByteArrayInputStream(content.toByteArray()), null, Accept.JSON_FULLMETA);
-    } catch (Exception e) {
-      LOG.error("While creating StoredPI", e);
-      return xml.createFaultResponse(Accept.JSON_FULLMETA.toString(), e);
-    }
-  }
-
-  @PATCH
-  @Path("/StoredPIs(1000)")
-  public Response patchStoredPI() {
-    // just for non nullable property test into PropertyTestITCase
-    return xml.createFaultResponse(Accept.JSON_FULLMETA.toString(), new Exception("Non nullable properties"));
-  }
-
-  // ----------------------------------------------
-
-  protected Response bodyPartRequest(final MimeBodyPart body) throws Exception {
-    return bodyPartRequest(body, Collections.<String, String> emptyMap());
-  }
-
-  protected Response bodyPartRequest(final MimeBodyPart body, final Map<String, String> references) throws Exception {
-    @SuppressWarnings("unchecked")
-    final Enumeration<Header> en = body.getAllHeaders();
-
-    Header header = en.nextElement();
-    final String request =
-        header.getName() + (StringUtils.isNotBlank(header.getValue()) ? ":" + header.getValue() : "");
-
-    final Matcher matcher = REQUEST_PATTERN.matcher(request);
-    final Matcher matcherRef = BATCH_REQUEST_REF_PATTERN.matcher(request);
-
-    final MultivaluedMap<String, String> headers = new MultivaluedHashMap<String, String>();
-
-    while (en.hasMoreElements()) {
-      header = en.nextElement();
-      headers.putSingle(header.getName(), header.getValue());
-    }
-
-    final Response res;
-    final String url;
-    final String method;
-
-    if (matcher.find()) {
-      url = matcher.group(2);
-      method = matcher.group(1);
-    } else if (matcherRef.find()) {
-      url = references.get(matcherRef.group(2)) + matcherRef.group(3);
-      method = matcherRef.group(1);
-    } else {
-      url = null;
-      method = null;
-    }
-
-    if (url == null) {
-      res = null;
-    } else {
-      final WebClient client = WebClient.create(url, "odatajclient", "odatajclient", null);
-      client.headers(headers);
-
-      if ("DELETE".equals(method)) {
-        res = client.delete();
-      } else {
-        final InputStream is = body.getDataHandler().getInputStream();
-        String content = IOUtils.toString(is);
-        IOUtils.closeQuietly(is);
-
-        final Matcher refs = REF_PATTERN.matcher(content);
-
-        while (refs.find()) {
-          content = content.replace(refs.group(1), references.get(refs.group(1)));
-        }
-
-        if ("PATCH".equals(method) || "MERGE".equals(method)) {
-          client.header("X-HTTP-METHOD", method);
-          res = client.invoke("POST", IOUtils.toInputStream(content));
-        } else {
-          res = client.invoke(method, IOUtils.toInputStream(content));
-        }
-      }
-
-      // When updating to CXF 3.0.1, uncomment the following line, see CXF-5865
-      // client.close();
-    }
-
-    return res;
-  }
-
-  protected abstract InputStream exploreMultipart(
-      final List<Attachment> attachments, final String boundary, final boolean continueOnError)
-          throws IOException;
-
-  protected void addItemIntro(final ByteArrayOutputStream bos) throws IOException {
-    addItemIntro(bos, null);
-  }
-
-  protected void addItemIntro(final ByteArrayOutputStream bos, final String contentId) throws IOException {
-    bos.write("Content-Type: application/http".getBytes());
-    bos.write(Constants.CRLF);
-    bos.write("Content-Transfer-Encoding: binary".getBytes());
-    bos.write(Constants.CRLF);
-
-    if (StringUtils.isNotBlank(contentId)) {
-      bos.write(("Content-ID: " + contentId).getBytes());
-      bos.write(Constants.CRLF);
-    }
-
-    bos.write(Constants.CRLF);
-  }
-
-  protected void addChangesetItemIntro(
-      final ByteArrayOutputStream bos, final String contentId, final String cboundary) throws IOException {
-    bos.write(("--" + cboundary).getBytes());
-    bos.write(Constants.CRLF);
-    bos.write(("Content-ID: " + contentId).getBytes());
-    bos.write(Constants.CRLF);
-    addItemIntro(bos);
-  }
-
-  protected void addSingleBatchResponse(
-      final Response response, final ByteArrayOutputStream bos) throws IOException {
-    addSingleBatchResponse(response, null, bos);
-  }
-
-  protected void addSingleBatchResponse(
-      final Response response, final String contentId, final ByteArrayOutputStream bos) throws IOException {
-    bos.write("HTTP/1.1 ".getBytes());
-    bos.write(String.valueOf(response.getStatusInfo().getStatusCode()).getBytes());
-    bos.write(" ".getBytes());
-    bos.write(response.getStatusInfo().getReasonPhrase().getBytes());
-    bos.write(Constants.CRLF);
-
-    for (Map.Entry<String, List<Object>> header : response.getHeaders().entrySet()) {
-      final StringBuilder builder = new StringBuilder();
-      for (Object value : header.getValue()) {
-        if (builder.length() > 0) {
-          builder.append(", ");
-        }
-        builder.append(value.toString());
-      }
-      builder.insert(0, ": ").insert(0, header.getKey());
-      bos.write(builder.toString().getBytes());
-      bos.write(Constants.CRLF);
-    }
-
-    if (StringUtils.isNotBlank(contentId)) {
-      bos.write(("Content-ID: " + contentId).getBytes());
-      bos.write(Constants.CRLF);
-    }
-
-    bos.write(Constants.CRLF);
-
-    final Object entity = response.getEntity();
-    if (entity != null) {
-      bos.write(IOUtils.toByteArray((InputStream) entity));
-      bos.write(Constants.CRLF);
-    }
-
-    bos.write(Constants.CRLF);
-  }
-
-  protected void addErrorBatchResponse(final Exception e, final ByteArrayOutputStream bos)
-      throws IOException {
-    addErrorBatchResponse(e, null, bos);
-  }
-
-  protected void addErrorBatchResponse(final Exception e, final String contentId, final ByteArrayOutputStream bos)
-      throws IOException {
-    addSingleBatchResponse(xml.createFaultResponse(Accept.XML.toString(), e), contentId, bos);
-  }
-
-  @PATCH
-  @Path("/{entitySetName}({entityId})")
-  @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_ATOM_XML, MediaType.APPLICATION_JSON })
-  @Consumes({ MediaType.APPLICATION_ATOM_XML, MediaType.APPLICATION_JSON })
-  public Response patchEntity(
-      @Context final UriInfo uriInfo,
-      @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept,
-      @HeaderParam("Content-Type") @DefaultValue(StringUtils.EMPTY) final String contentType,
-      @HeaderParam("Prefer") @DefaultValue(StringUtils.EMPTY) final String prefer,
-      @HeaderParam("If-Match") @DefaultValue(StringUtils.EMPTY) final String ifMatch,
-      @PathParam("entitySetName") final String entitySetName,
-      @PathParam("entityId") final String entityId,
-      final String changes) {
-
-    try {
-      final Accept acceptType = Accept.parse(accept);
-
-      if (acceptType == Accept.XML || acceptType == Accept.TEXT) {
-        throw new UnsupportedMediaTypeException("Unsupported media type");
-      }
-
-      final Map.Entry<String, InputStream> entityInfo = xml.readEntity(entitySetName, entityId, Accept.ATOM);
-
-      final String etag = Commons.getETag(entityInfo.getKey());
-      if (StringUtils.isNotBlank(ifMatch) && !ifMatch.equals(etag)) {
-        throw new ConcurrentModificationException("Concurrent modification");
-      }
-
-      final Accept contentTypeValue = Accept.parse(contentType);
-
-      final Entity entryChanges;
-
-      if (contentTypeValue == Accept.XML || contentTypeValue == Accept.TEXT) {
-        throw new UnsupportedMediaTypeException("Unsupported media type");
-      } else if (contentTypeValue == Accept.ATOM) {
-        entryChanges = atomDeserializer.toEntity(
-            IOUtils.toInputStream(changes, Constants.ENCODING)).getPayload();
-      } else {
-        final ResWrap<Entity> jcont = jsonDeserializer.toEntity(IOUtils.toInputStream(changes, Constants.ENCODING));
-        entryChanges = jcont.getPayload();
-      }
-
-      final ResWrap<Entity> container = atomDeserializer.toEntity(entityInfo.getValue());
-
-      for (Property property : entryChanges.getProperties()) {
-        final Property _property = container.getPayload().getProperty(property.getName());
-        if (_property == null) {
-          container.getPayload().getProperties().add(property);
-        } else {
-          _property.setValue(property.getValueType(), property.getValue());
-        }
-      }
-
-      for (Link link : entryChanges.getNavigationLinks()) {
-        container.getPayload().getNavigationLinks().add(link);
-      }
-
-      final ByteArrayOutputStream content = new ByteArrayOutputStream();
-      final OutputStreamWriter writer = new OutputStreamWriter(content, Constants.ENCODING);
-      atomSerializer.write(writer, container);
-      writer.flush();
-      writer.close();
-
-      final InputStream res = xml.addOrReplaceEntity(
-          entityId, entitySetName, new ByteArrayInputStream(content.toByteArray()), container.getPayload());
-
-      final ResWrap<Entity> cres = atomDeserializer.toEntity(res);
-
-      normalizeAtomEntry(cres.getPayload(), entitySetName, entityId);
-
-      final String path = Commons.getEntityBasePath(entitySetName, entityId);
-      FSManager.instance(version).putInMemory(
-          cres, path + File.separatorChar + Constants.get(ConstantKey.ENTITY));
-
-      final Response response;
-      if ("return-content".equalsIgnoreCase(prefer)) {
-        response = xml.createResponse(
-            uriInfo.getRequestUri().toASCIIString(),
-            xml.readEntity(entitySetName, entityId, acceptType).getValue(),
-            null, acceptType, Response.Status.OK);
-      } else {
-        res.close();
-        response = xml.createResponse(
-            uriInfo.getRequestUri().toASCIIString(),
-            null,
-            null,
-            acceptType, Response.Status.NO_CONTENT);
-      }
-
-      if (StringUtils.isNotBlank(prefer)) {
-        response.getHeaders().put("Preference-Applied", Collections.<Object> singletonList(prefer));
-      }
-
-      return response;
-    } catch (Exception e) {
-      return xml.createFaultResponse(accept, e);
-    }
-  }
-
-  @PUT
-  @Path("/{entitySetName}({entityId})")
-  @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_ATOM_XML, MediaType.APPLICATION_JSON })
-  @Consumes({ MediaType.APPLICATION_ATOM_XML, MediaType.APPLICATION_JSON })
-  public Response replaceEntity(
-      @Context final UriInfo uriInfo,
-      @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept,
-      @HeaderParam("Content-Type") @DefaultValue(StringUtils.EMPTY) final String contentType,
-      @HeaderParam("Prefer") @DefaultValue(StringUtils.EMPTY) final String prefer,
-      @PathParam("entitySetName") final String entitySetName,
-      @PathParam("entityId") final String entityId,
-      final String entity) {
-
-    try {
-      final Accept acceptType = Accept.parse(accept);
-
-      if (acceptType == Accept.XML || acceptType == Accept.TEXT) {
-        throw new UnsupportedMediaTypeException("Unsupported media type");
-      }
-
-      final InputStream res = getUtilities(acceptType).addOrReplaceEntity(entityId, entitySetName,
-          IOUtils.toInputStream(entity, Constants.ENCODING),
-          xml.readEntity(acceptType, IOUtils.toInputStream(entity, Constants.ENCODING)));
-
-      final ResWrap<Entity> cres;
-      if (acceptType == Accept.ATOM) {
-        cres = atomDeserializer.toEntity(res);
-      } else {
-        cres = jsonDeserializer.toEntity(res);
-      }
-
-      final String path = Commons.getEntityBasePath(entitySetName, entityId);
-      FSManager.instance(version).putInMemory(
-          cres, path + File.separatorChar + Constants.get(ConstantKey.ENTITY));
-
-      final Response response;
-      if ("return-content".equalsIgnoreCase(prefer)) {
-        response = xml.createResponse(
-            uriInfo.getRequestUri().toASCIIString(),
-            xml.readEntity(entitySetName, entityId, acceptType).getValue(),
-            null,
-            acceptType,
-            Response.Status.OK);
-      } else {
-        res.close();
-        response = xml.createResponse(
-            uriInfo.getRequestUri().toASCIIString(),
-            null,
-            null,
-            acceptType,
-            Response.Status.NO_CONTENT);
-      }
-
-      if (StringUtils.isNotBlank(prefer)) {
-        response.getHeaders().put("Preference-Applied", Collections.<Object> singletonList(prefer));
-      }
-
-      return response;
-    } catch (Exception e) {
-      return xml.createFaultResponse(accept, e);
-    }
-  }
-
-  @POST
-  @Path("/{entitySetName}")
-  @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_ATOM_XML, MediaType.APPLICATION_JSON })
-  @Consumes({ MediaType.APPLICATION_ATOM_XML, MediaType.APPLICATION_JSON, MediaType.APPLICATION_OCTET_STREAM })
-  public Response postNewEntity(
-      @Context final UriInfo uriInfo,
-      @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept,
-      @HeaderParam("Content-Type") @DefaultValue(StringUtils.EMPTY) final String contentType,
-      @HeaderParam("Prefer") @DefaultValue(StringUtils.EMPTY) final String prefer,
-      @PathParam("entitySetName") final String entitySetName,
-      final String entity) {
-
-    try {
-      final Accept acceptType = Accept.parse(accept);
-      if (acceptType == Accept.XML || acceptType == Accept.TEXT) {
-        throw new UnsupportedMediaTypeException("Unsupported media type");
-      }
-
-      final ResWrap<Entity> container;
-
-      final org.apache.olingo.fit.metadata.EntitySet entitySet = metadata.getEntitySet(entitySetName);
-
-      final Entity entry;
-      final String entityKey;
-      if (xml.isMediaContent(entitySetName)) {
-        entry = new Entity();
-        entry.setMediaContentType(ContentType.APPLICATION_OCTET_STREAM.toContentTypeString());
-        entry.setType(entitySet.getType());
-
-        entityKey = xml.getDefaultEntryKey(entitySetName, entry);
-
-        xml.addMediaEntityValue(entitySetName, entityKey, IOUtils.toInputStream(entity, Constants.ENCODING));
-
-        final Pair<String, EdmPrimitiveTypeKind> id = Commons.getMediaContent().get(entitySetName);
-        if (id != null) {
-          final Property prop = new Property();
-          prop.setName(id.getKey());
-          prop.setType(id.getValue().toString());
-          prop.setValue(ValueType.PRIMITIVE,
-              id.getValue() == EdmPrimitiveTypeKind.Int32
-              ? Integer.parseInt(entityKey)
-                  : id.getValue() == EdmPrimitiveTypeKind.Guid
-                  ? UUID.fromString(entityKey)
-                      : entityKey);
-          entry.getProperties().add(prop);
-        }
-
-        final Link editLink = new Link();
-        editLink.setHref(Commons.getEntityURI(entitySetName, entityKey));
-        editLink.setRel("edit");
-        editLink.setTitle(entitySetName);
-        entry.setEditLink(editLink);
-
-        entry.setMediaContentSource(URI.create(editLink.getHref() + "/$value"));
-
-        container = new ResWrap<Entity>((URI) null, null, entry);
-      } else {
-        final Accept contentTypeValue = Accept.parse(contentType);
-        if (Accept.ATOM == contentTypeValue) {
-          container = atomDeserializer.toEntity(IOUtils.toInputStream(entity, Constants.ENCODING));
-        } else {
-          container = jsonDeserializer.toEntity(IOUtils.toInputStream(entity, Constants.ENCODING));
-        }
-        entry = container.getPayload();
-        updateInlineEntities(entry);
-
-        entityKey = xml.getDefaultEntryKey(entitySetName, entry);
-      }
-
-      normalizeAtomEntry(entry, entitySetName, entityKey);
-
-      final ByteArrayOutputStream content = new ByteArrayOutputStream();
-      final OutputStreamWriter writer = new OutputStreamWriter(content, Constants.ENCODING);
-      atomSerializer.write(writer, container);
-      writer.flush();
-      writer.close();
-
-      final InputStream serialization =
-          xml.addOrReplaceEntity(entityKey, entitySetName, new ByteArrayInputStream(content.toByteArray()), entry);
-
-      ResWrap<Entity> result = atomDeserializer.toEntity(serialization);
-      result = new ResWrap<Entity>(
-          URI.create(Constants.get(ConstantKey.ODATA_METADATA_PREFIX)
-              + entitySetName + Constants.get(ConstantKey.ODATA_METADATA_ENTITY_SUFFIX)),
-              null, result.getPayload());
-
-      final String path = Commons.getEntityBasePath(entitySetName, entityKey);
-      FSManager.instance(version).putInMemory(result, path + Constants.get(ConstantKey.ENTITY));
-
-      final String location;
-
-      if ((this instanceof KeyAsSegment)) {
-        location = uriInfo.getRequestUri().toASCIIString() + "/" + entityKey;
-
-        final Link editLink = new Link();
-        editLink.setRel("edit");
-        editLink.setTitle(entitySetName);
-        editLink.setHref(location);
-
-        result.getPayload().setEditLink(editLink);
-      } else {
-        location = uriInfo.getRequestUri().toASCIIString() + "(" + entityKey + ")";
-      }
-
-      final Response response;
-      if ("return-no-content".equalsIgnoreCase(prefer)) {
-        response = xml.createResponse(
-            location,
-            null,
-            null,
-            acceptType,
-            Response.Status.NO_CONTENT);
-      } else {
-        response = xml.createResponse(
-            location,
-            xml.writeEntity(acceptType, result),
-            null,
-            acceptType,
-            Response.Status.CREATED);
-      }
-
-      if (StringUtils.isNotBlank(prefer)) {
-        response.getHeaders().put("Preference-Applied", Collections.<Object> singletonList(prefer));
-      }
-
-      return response;
-    } catch (Exception e) {
-      LOG.error("While creating new entity", e);
-      return xml.createFaultResponse(accept, e);
-    }
-  }
-
-  @POST
-  @Path("/Person({entityId})/{type:.*}/Sack")
-  public Response actionSack(
-      @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept,
-      @PathParam("entityId") final String entityId,
-      @PathParam("type") final String type,
-      @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format) {
-
-    final Map.Entry<Accept, AbstractUtilities> utils = getUtilities(accept, format);
-
-    if (utils.getKey() == Accept.XML || utils.getKey() == Accept.TEXT) {
-      throw new UnsupportedMediaTypeException("Unsupported media type");
-    }
-
-    try {
-      final Map.Entry<String, InputStream> entityInfo = xml.readEntity("Person", entityId, Accept.ATOM);
-
-      final InputStream entity = entityInfo.getValue();
-      final ResWrap<Entity> container = atomDeserializer.toEntity(entity);
-
-      container.getPayload().getProperty("Salary").setValue(ValueType.PRIMITIVE, 0);
-      container.getPayload().getProperty("Title").setValue(ValueType.PRIMITIVE, "[Sacked]");
-
-      final FSManager fsManager = FSManager.instance(version);
-      fsManager.putInMemory(xml.writeEntity(Accept.ATOM, container),
-          fsManager.getAbsolutePath(Commons.getEntityBasePath("Person", entityId) + Constants.get(
-              ConstantKey.ENTITY), Accept.ATOM));
-
-      return utils.getValue().createResponse(null, null, null, utils.getKey(), Response.Status.NO_CONTENT);
-    } catch (Exception e) {
-      return xml.createFaultResponse(accept, e);
-    }
-  }
-
-  @POST
-  @Path("/Person/{type:.*}/IncreaseSalaries")
-  public Response actionIncreaseSalaries(
-      @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept,
-      @PathParam("type") final String type,
-      @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format,
-      final String body) {
-
-    final String name = "Person";
-    try {
-      final Accept acceptType = Accept.parse(accept);
-      if (acceptType == Accept.XML || acceptType == Accept.TEXT) {
-        throw new UnsupportedMediaTypeException("Unsupported media type");
-      }
-
-      final JsonNode tree = new ObjectMapper().readTree(body);
-      if (!tree.has("n")) {
-        throw new Exception("Missing parameter: n");
-      }
-      final int n = tree.get("n").asInt();
-
-      final StringBuilder path = new StringBuilder(name).
-          append(File.separatorChar).append(type).
-          append(File.separatorChar);
-
-      path.append(metadata.getEntitySet(name).isSingleton()
-          ? Constants.get(ConstantKey.ENTITY)
-              : Constants.get(ConstantKey.FEED));
-
-      final InputStream feed = FSManager.instance(version).readFile(path.toString(), acceptType);
-
-      final ByteArrayOutputStream copy = new ByteArrayOutputStream();
-      IOUtils.copy(feed, copy);
-      IOUtils.closeQuietly(feed);
-
-      String newContent = new String(copy.toByteArray(), "UTF-8");
-      final Pattern salary = Pattern.compile(acceptType == Accept.ATOM
-          ? "\\<d:Salary m:type=\"Edm.Int32\"\\>(-?\\d+)\\</d:Salary\\>"
-              : "\"Salary\":(-?\\d+),");
-      final Matcher salaryMatcher = salary.matcher(newContent);
-      while (salaryMatcher.find()) {
-        final Long newSalary = Long.valueOf(salaryMatcher.group(1)) + n;
-        newContent = newContent.
-            replaceAll("\"Salary\":" + salaryMatcher.group(1) + ",",
-                "\"Salary\":" + newSalary + ",").
-                replaceAll("\\<d:Salary m:type=\"Edm.Int32\"\\>" + salaryMatcher.group(1) + "</d:Salary\\>",
-                    "<d:Salary m:type=\"Edm.Int32\">" + newSalary + "</d:Salary>");
-      }
-
-      FSManager.instance(version).putInMemory(IOUtils.toInputStream(newContent, Constants.ENCODING),
-          FSManager.instance(version).getAbsolutePath(path.toString(), acceptType));
-
-      return xml.createResponse(null, null, null, acceptType, Response.Status.NO_CONTENT);
-    } catch (Exception e) {
-      return xml.createFaultResponse(accept, e);
-    }
-  }
-
-  @POST
-  @Path("/Product({entityId})/ChangeProductDimensions")
-  public Response actionChangeProductDimensions(
-      @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept,
-      @PathParam("entityId") final String entityId,
-      @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format,
-      final String argument) {
-
-    final Map.Entry<Accept, AbstractUtilities> utils = getUtilities(accept, format);
-
-    if (utils.getKey() == Accept.XML || utils.getKey() == Accept.TEXT) {
-      throw new UnsupportedMediaTypeException("Unsupported media type");
-    }
-
-    try {
-      final Map.Entry<String, InputStream> entityInfo = xml.readEntity("Product", entityId, Accept.ATOM);
-
-      final InputStream entity = entityInfo.getValue();
-      final ResWrap<Entity> container = atomDeserializer.toEntity(entity);
-
-      final Entity param = xml.readEntity(utils.getKey(), IOUtils.toInputStream(argument, Constants.ENCODING));
-
-      final Property property = param.getProperty("dimensions");
-      container.getPayload().getProperty("Dimensions").setValue(property.getValueType(), property.getValue());
-
-      final FSManager fsManager = FSManager.instance(version);
-      fsManager.putInMemory(xml.writeEntity(Accept.ATOM, container),
-          fsManager.getAbsolutePath(Commons.getEntityBasePath("Product", entityId) + Constants.get(
-              ConstantKey.ENTITY), Accept.ATOM));
-
-      return utils.getValue().createResponse(null, null, null, utils.getKey(), Response.Status.NO_CONTENT);
-    } catch (Exception e) {
-      return xml.createFaultResponse(accept, e);
-    }
-  }
-
-  @POST
-  @Path("/ComputerDetail({entityId})/ResetComputerDetailsSpecifications")
-  public Response actionResetComputerDetailsSpecifications(
-      @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept,
-      @PathParam("entityId") final String entityId,
-      @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format,
-      final String argument) {
-
-    final Map.Entry<Accept, AbstractUtilities> utils = getUtilities(accept, format);
-
-    if (utils.getKey() == Accept.XML || utils.getKey() == Accept.TEXT) {
-      throw new UnsupportedMediaTypeException("Unsupported media type");
-    }
-
-    try {
-      final Map.Entry<String, InputStream> entityInfo = xml.readEntity("ComputerDetail", entityId, Accept.ATOM);
-
-      final InputStream entity = entityInfo.getValue();
-      final ResWrap<Entity> container = atomDeserializer.toEntity(entity);
-
-      final Entity param = xml.readEntity(utils.getKey(), IOUtils.toInputStream(argument, Constants.ENCODING));
-
-      Property property = param.getProperty("specifications");
-      container.getPayload().getProperty("SpecificationsBag").setValue(property.getValueType(), property.getValue());
-      property = param.getProperty("purchaseTime");
-      container.getPayload().getProperty("PurchaseDate").setValue(property.getValueType(), property.getValue());
-
-      final FSManager fsManager = FSManager.instance(version);
-      fsManager.putInMemory(xml.writeEntity(Accept.ATOM, container),
-          fsManager.getAbsolutePath(Commons.getEntityBasePath("ComputerDetail", entityId) + Constants.get(
-              ConstantKey.ENTITY), Accept.ATOM));
-
-      return utils.getValue().createResponse(null, null, null, utils.getKey(), Response.Status.NO_CONTENT);
-    } catch (Exception e) {
-      return xml.createFaultResponse(accept, e);
-    }
-  }
-
-  /**
-   * Retrieve entities from the given entity set and the given type.
-   *
-   * @param accept Accept header.
-   * @param name entity set.
-   * @param type entity type.
-   * @return entity set.
-   */
-  @GET
-  @Path("/{name}/{type:[a-zA-Z].*}")
-  public Response getEntitySet(
-      @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept,
-      @PathParam("name") final String name,
-      @PathParam("type") final String type) {
-
-    try {
-      final Accept acceptType = Accept.parse(accept);
-      if (acceptType == Accept.XML || acceptType == Accept.TEXT) {
-        throw new UnsupportedMediaTypeException("Unsupported media type");
-      }
-
-      final String basePath = name + File.separatorChar;
-      final StringBuilder path = new StringBuilder(name).
-          append(File.separatorChar).append(type).
-          append(File.separatorChar);
-
-      path.append(metadata.getEntitySet(name).isSingleton()
-          ? Constants.get(ConstantKey.ENTITY)
-              : Constants.get(ConstantKey.FEED));
-
-      final InputStream feed = FSManager.instance(version).readFile(path.toString(), acceptType);
-      return xml.createResponse(null, feed, Commons.getETag(basePath), acceptType);
-    } catch (Exception e) {
-      return xml.createFaultResponse(accept, e);
-    }
-  }
-
-  @GET
-  @Path("/{name}/{type:[a-zA-Z].*}")
-  public Response getEntitySet(@Context final UriInfo uriInfo,
-      @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept,
-      @PathParam("name") final String name,
-      @QueryParam("$top") @DefaultValue(StringUtils.EMPTY) final String top,
-      @QueryParam("$skip") @DefaultValue(StringUtils.EMPTY) final String skip,
-      @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format,
-      @QueryParam("$count") @DefaultValue(StringUtils.EMPTY) final String count,
-      @QueryParam("$filter") @DefaultValue(StringUtils.EMPTY) final String filter,
-      @QueryParam("$orderby") @DefaultValue(StringUtils.EMPTY) final String orderby,
-      @QueryParam("$skiptoken") @DefaultValue(StringUtils.EMPTY) final String skiptoken,
-      @PathParam("type") final String type) {
-
-    try {
-      final Accept acceptType;
-      if (StringUtils.isNotBlank(format)) {
-        acceptType = Accept.valueOf(format.toUpperCase());
-      } else {
-        acceptType = Accept.parse(accept);
-      }
-
-      final String location = uriInfo.getRequestUri().toASCIIString();
-      try {
-        // search for function ...
-        final InputStream func = FSManager.instance(version).readFile(name, acceptType);
-        return xml.createResponse(location, func, null, acceptType);
-      } catch (NotFoundException e) {
-        if (acceptType == Accept.XML || acceptType == Accept.TEXT) {
-          throw new UnsupportedMediaTypeException("Unsupported media type");
-        }
-
-        // search for entitySet ...
-        final String basePath = name + File.separatorChar;
-
-        final StringBuilder builder = new StringBuilder();
-        builder.append(basePath);
-
-        if (type != null) {
-          builder.append(type).append(File.separatorChar);
-        }
-
-        if (StringUtils.isNotBlank(orderby)) {
-          builder.append(Constants.get(ConstantKey.ORDERBY)).append(File.separatorChar).
-          append(orderby).append(File.separatorChar);
-        }
-
-        if (StringUtils.isNotBlank(filter)) {
-          builder.append(Constants.get(ConstantKey.FILTER)).append(File.separatorChar).
-          append(filter.replaceAll("/", "."));
-        } else if (StringUtils.isNotBlank(skiptoken)) {
-          builder.append(Constants.get(ConstantKey.SKIP_TOKEN)).append(File.separatorChar).
-          append(skiptoken);
-        } else {
-          builder.append(metadata.getEntitySet(name).isSingleton()
-              ? Constants.get(ConstantKey.ENTITY)
-                  : Constants.get(ConstantKey.FEED));
-        }
-
-        final InputStream feed = FSManager.instance(version).readFile(builder.toString(), Accept.ATOM);
-
-        final ResWrap<EntityCollection> container = atomDeserializer.toEntitySet(feed);
-
-        setInlineCount(container.getPayload(), count);
-
-        final ByteArrayOutputStream content = new ByteArrayOutputStream();
-        final OutputStreamWriter writer = new OutputStreamWriter(content, Constants.ENCODING);
-
-        // -----------------------------------------------
-        // Evaluate $skip and $top
-        // -----------------------------------------------
-        List<Entity> entries = new ArrayList<Entity>(container.getPayload().getEntities());
-
-        if (StringUtils.isNotBlank(skip)) {
-          entries = entries.subList(Integer.valueOf(skip), entries.size());
-        }
-
-        if (StringUtils.isNotBlank(top)) {
-          entries = entries.subList(0, Integer.valueOf(top));
-        }
-
-        container.getPayload().getEntities().clear();
-        container.getPayload().getEntities().addAll(entries);
-        // -----------------------------------------------
-
-        if (acceptType == Accept.ATOM) {
-          atomSerializer.write(writer, container);
-        } else {
-          jsonSerializer.write(writer, container);
-        }
-        writer.flush();
-        writer.close();
-
-        return xml.createResponse(
-            location,
-            new ByteArrayInputStream(content.toByteArray()),
-            Commons.getETag(basePath),
-            acceptType);
-      }
-    } catch (Exception e) {
-      return xml.createFaultResponse(accept, e);
-    }
-  }
-
-  /**
-   * Retrieve entity set or function execution sample.
-   *
-   * @param accept Accept header.
-   * @param name entity set or function name.
-   * @param format format query option.
-   * @param count count query option.
-   * @param filter filter query option.
-   * @param orderby orderby query option.
-   * @param skiptoken skiptoken query option.
-   * @return entity set or function result.
-   */
-  @GET
-  @Path("/{name}")
-  public Response getEntitySet(
-      @Context final UriInfo uriInfo,
-      @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept,
-      @PathParam("name") final String name,
-      @QueryParam("$top") @DefaultValue(StringUtils.EMPTY) final String top,
-      @QueryParam("$skip") @DefaultValue(StringUtils.EMPTY) final String skip,
-      @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format,
-      @QueryParam("$count") @DefaultValue(StringUtils.EMPTY) final String count,
-      @QueryParam("$filter") @DefaultValue(StringUtils.EMPTY) final String filter,
-      @QueryParam("$orderby") @DefaultValue(StringUtils.EMPTY) final String orderby,
-      @QueryParam("$skiptoken") @DefaultValue(StringUtils.EMPTY) final String skiptoken) {
-
-    return getEntitySet(uriInfo, accept, name, top, skip, format, count, filter, orderby, skiptoken, null);
-  }
-
-  protected abstract void setInlineCount(final EntityCollection feed, final String count);
-
-  @GET
-  @Path("/Person({entityId})")
-  public Response getPerson(
-      @Context final UriInfo uriInfo,
-      @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept,
-      @PathParam("entityId") final String entityId,
-      @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format) {
-
-    final Map.Entry<Accept, AbstractUtilities> utils = getUtilities(accept, format);
-
-    final Response internal = getEntityInternal(
-        uriInfo.getRequestUri().toASCIIString(), accept, "Person", entityId, format, null, null);
-    if (internal.getStatus() == 200) {
-      InputStream entity = (InputStream) internal.getEntity();
-      try {
-        if (utils.getKey() == Accept.JSON_FULLMETA || utils.getKey() == Accept.ATOM) {
-          entity = utils.getValue().addOperation(entity, "Sack", "#DefaultContainer.Sack",
-              uriInfo.getAbsolutePath().toASCIIString()
-              + "/Microsoft.Test.OData.Services.AstoriaDefaultService.SpecialEmployee/Sack");
-        }
-
-        return utils.getValue().createResponse(
-            uriInfo.getRequestUri().toASCIIString(),
-            entity,
-            internal.getHeaderString("ETag"),
-            utils.getKey());
-      } catch (Exception e) {
-        LOG.error("Error retrieving entity", e);
-        return xml.createFaultResponse(accept, e);
-      }
-    } else {
-      return internal;
-    }
-  }
-
-  @GET
-  @Path("/Product({entityId})")
-  public Response getProduct(
-      @Context final UriInfo uriInfo,
-      @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept,
-      @PathParam("entityId") final String entityId,
-      @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format) {
-
-    final Map.Entry<Accept, AbstractUtilities> utils = getUtilities(accept, format);
-
-    final Response internal = getEntityInternal(
-        uriInfo.getRequestUri().toASCIIString(), accept, "Product", entityId, format, null, null);
-    if (internal.getStatus() == 200) {
-      InputStream entity = (InputStream) internal.getEntity();
-      try {
-        if (utils.getKey() == Accept.JSON_FULLMETA || utils.getKey() == Accept.ATOM) {
-          entity = utils.getValue().addOperation(entity,
-              "ChangeProductDimensions", "#DefaultContainer.ChangeProductDimensions",
-              uriInfo.getAbsolutePath().toASCIIString() + "/ChangeProductDimensions");
-        }
-
-        return utils.getValue().createResponse(
-            uriInfo.getRequestUri().toASCIIString(),
-            entity,
-            internal.getHeaderString("ETag"),
-            utils.getKey());
-      } catch (Exception e) {
-        LOG.error("Error retrieving entity", e);
-        return xml.createFaultResponse(accept, e);
-      }
-    } else {
-      return internal;
-    }
-  }
-
-  @GET
-  @Path("/ComputerDetail({entityId})")
-  public Response getComputerDetail(
-      @Context final UriInfo uriInfo,
-      @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept,
-      @PathParam("entityId") final String entityId,
-      @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format) {
-
-    final Map.Entry<Accept, AbstractUtilities> utils = getUtilities(accept, format);
-
-    final Response internal = getEntityInternal(
-        uriInfo.getRequestUri().toASCIIString(), accept, "ComputerDetail", entityId, format, null, null);
-    if (internal.getStatus() == 200) {
-      InputStream entity = (InputStream) internal.getEntity();
-      try {
-        if (utils.getKey() == Accept.JSON_FULLMETA || utils.getKey() == Accept.ATOM) {
-          entity = utils.getValue().addOperation(entity,
-              "ResetComputerDetailsSpecifications", "#DefaultContainer.ResetComputerDetailsSpecifications",
-              uriInfo.getAbsolutePath().toASCIIString() + "/ResetComputerDetailsSpecifications");
-        }
-
-        return utils.getValue().createResponse(
-            uriInfo.getRequestUri().toASCIIString(),
-            entity,
-            internal.getHeaderString("ETag"),
-            utils.getKey());
-      } catch (Exception e) {
-        LOG.error("Error retrieving entity", e);
-        return xml.createFaultResponse(accept, e);
-      }
-    } else {
-      return internal;
-    }
-  }
-
-  /**
-   * Retrieve entity sample.
-   *
-   * @param accept Accept header.
-   * @param entitySetName Entity set name.
-   * @param entityId entity id.
-   * @param format format query option.
-   * @param expand expand query option.
-   * @param select select query option.
-   * @return entity.
-   */
-  @GET
-  @Path("/{entitySetName}({entityId})")
-  public Response getEntity(
-      @Context final UriInfo uriInfo,
-      @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept,
-      @PathParam("entitySetName") final String entitySetName,
-      @PathParam("entityId") final String entityId,
-      @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format,
-      @QueryParam("$expand") @DefaultValue(StringUtils.EMPTY) final String expand,
-      @QueryParam("$select") @DefaultValue(StringUtils.EMPTY) final String select) {
-
-    return getEntityInternal(
-        uriInfo.getRequestUri().toASCIIString(), accept, entitySetName, entityId, format, expand, select);
-  }
-
-  protected Response getEntityInternal(
-      final String location,
-      final String accept,
-      final String entitySetName,
-      final String entityId,
-      final String format,
-      final String expand,
-      final String select) {
-
-    try {
-      final Map.Entry<Accept, AbstractUtilities> utils = getUtilities(accept, format);
-
-      if (utils.getKey() == Accept.XML || utils.getKey() == Accept.TEXT) {
-        throw new UnsupportedMediaTypeException("Unsupported media type");
-      }
-
-      final Map.Entry<String, InputStream> entityInfo =
-          utils.getValue().readEntity(entitySetName, entityId, Accept.ATOM);
-
-      final InputStream entity = entityInfo.getValue();
-
-      ResWrap<Entity> container = atomDeserializer.toEntity(entity);
-      if (container.getContextURL() == null) {
-        container = new ResWrap<Entity>(URI.create(Constants.get(ConstantKey.ODATA_METADATA_PREFIX)
-            + entitySetName + Constants.get(ConstantKey.ODATA_METADATA_ENTITY_SUFFIX)),
-            container.getMetadataETag(), container.getPayload());
-      }
-      final Entity entry = container.getPayload();
-
-      if ((this instanceof KeyAsSegment)) {
-        final Link editLink = new Link();
-        editLink.setRel("edit");
-        editLink.setTitle(entitySetName);
-        editLink.setHref(Constants.get(ConstantKey.DEFAULT_SERVICE_URL) + entitySetName + "/" + entityId);
-
-        entry.setEditLink(editLink);
-      }
-
-      if (StringUtils.isNotBlank(select)) {
-        final List<String> properties = Arrays.asList(select.split(","));
-        final Set<Property> toBeRemoved = new HashSet<Property>();
-
-        for (Property property : entry.getProperties()) {
-          if (!properties.contains(property.getName())) {
-            toBeRemoved.add(property);
-          }
-        }
-
-        entry.getProperties().removeAll(toBeRemoved);
-
-        final Set<Link> linkToBeRemoved = new HashSet<Link>();
-
-        for (Link link : entry.getNavigationLinks()) {
-          if (!properties.contains(link.getTitle().replaceAll("@.*$", "")) && !properties.contains(link.getTitle())) {
-            linkToBeRemoved.add(link);
-          }
-        }
-
-        entry.getNavigationLinks().removeAll(linkToBeRemoved);
-      }
-
-      String tempExpand = expand;
-      if (StringUtils.isNotBlank(tempExpand)) {
-        tempExpand = StringUtils.substringBefore(tempExpand, "(");
-        final List<String> links = Arrays.asList(tempExpand.split(","));
-
-        final Map<Link, Link> replace = new HashMap<Link, Link>();
-
-        for (Link link : entry.getNavigationLinks()) {
-          if (links.contains(link.getTitle())) {
-            // expand link
-            final Link rep = new Link();
-            rep.setHref(link.getHref());
-            rep.setRel(link.getRel());
-            rep.setTitle(link.getTitle());
-            rep.setType(link.getType());
-            if (link.getType().equals(Constants.get(ConstantKey.ATOM_LINK_ENTRY))) {
-              // inline entry
-              final Entity inline = atomDeserializer.toEntity(
-                  xml.expandEntity(entitySetName, entityId, link.getTitle())).getPayload();
-              rep.setInlineEntity(inline);
-            } else if (link.getType().equals(Constants.get(ConstantKey.ATOM_LINK_FEED))) {
-              // inline feed
-              final EntityCollection inline = atomDeserializer.toEntitySet(
-                  xml.expandEntity(entitySetName, entityId, link.getTitle())).getPayload();
-              rep.setInlineEntitySet(inline);
-            }
-            replace.put(link, rep);
-          }
-        }
-
-        for (Map.Entry<Link, Link> link : replace.entrySet()) {
-          entry.getNavigationLinks().remove(link.getKey());
-          entry.getNavigationLinks().add(link.getValue());
-        }
-      }
-
-      return xml.createResponse(
-          location,
-          xml.writeEntity(utils.getKey(), container),
-          Commons.getETag(entityInfo.getKey()),
-          utils.getKey());
-    } catch (Exception e) {
-      LOG.error("Error retrieving entity", e);
-      return xml.createFaultResponse(accept, e);
-    }
-  }
-
-  @GET
-  @Path("/{entitySetName}({entityId})/$value")
-  public Response getMediaEntity(
-      @Context final UriInfo uriInfo,
-      @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept,
-      @PathParam("entitySetName") final String entitySetName,
-      @PathParam("entityId") final String entityId) {
-
-    try {
-      if (!accept.contains("*/*") && !accept.contains("application/octet-stream")) {
-        throw new UnsupportedMediaTypeException("Unsupported media type");
-      }
-
-      final AbstractUtilities utils = getUtilities(null);
-      final Map.Entry<String, InputStream> entityInfo = utils.readMediaEntity(entitySetName, entityId);
-      return utils.createResponse(
-          uriInfo.getRequestUri().toASCIIString(),
-          entityInfo.getValue(),
-          Commons.getETag(entityInfo.getKey()),
-          null);
-
-    } catch (Exception e) {
-      LOG.error("Error retrieving entity", e);
-      return xml.createFaultResponse(accept, e);
-    }
-  }
-
-  @DELETE
-  @Path("/{entitySetName}({entityId})")
-  public Response removeEntity(
-      @PathParam("entitySetName") final String entitySetName,
-      @PathParam("entityId") final String entityId) {
-
-    try {
-      final String basePath = entitySetName + File.separatorChar + Commons.getEntityKey(entityId);
-
-      FSManager.instance(version).deleteEntity(basePath);
-
-      return xml.createResponse(null, null, null, null, Response.Status.NO_CONTENT);
-    } catch (Exception e) {
-      return xml.createFaultResponse(Accept.XML.toString(), e);
-    }
-  }
-
-  private Response replaceProperty(
-      final String location,
-      final String accept,
-      final String contentType,
-      final String prefer,
-      final String entitySetName,
-      final String entityId,
-      final String path,
-      final String format,
-      final String changes,
-      final boolean justValue) {
-
-    // if the given path is not about any link then search for property
-    LOG.info("Retrieve property {}", path);
-
-    try {
-      final FSManager fsManager = FSManager.instance(version);
-      final String basePath = Commons.getEntityBasePath(entitySetName, entityId);
-
-      final ResWrap<Entity> container = xml.readContainerEntity(Accept.ATOM,
-          fsManager.readFile(basePath + Constants.get(ConstantKey.ENTITY), Accept.ATOM));
-
-      final Entity entry = container.getPayload();
-
-      Property toBeReplaced = null;
-      for (String element : path.split("/")) {
-        if (toBeReplaced == null) {
-          toBeReplaced = entry.getProperty(element.trim());
-        } else {
-          List<Property> value = toBeReplaced.asComplex().getValue();
-          for (Property field : value) {
-            if (field.getName().equalsIgnoreCase(element)) {
-              toBeReplaced = field;
-            }
-          }
-        }
-      }
-
-      if (toBeReplaced == null) {
-        throw new NotFoundException();
-      }
-
-      if (justValue) {
-        // just for primitive values
-        toBeReplaced.setValue(ValueType.PRIMITIVE, changes);
-      } else {
-        final Property pchanges = xml.readProperty(
-            Accept.parse(contentType),
-            IOUtils.toInputStream(changes, Constants.ENCODING));
-
-        toBeReplaced.setValue(pchanges.getValueType(), pchanges.getValue());
-      }
-
-      fsManager.putInMemory(xml.writeEntity(Accept.ATOM, container),
-          fsManager.getAbsolutePath(basePath + Constants.get(ConstantKey.ENTITY), Accept.ATOM));
-
-      final Response response;
-      if ("return-content".equalsIgnoreCase(prefer)) {
-        response = getEntityInternal(location, accept, entitySetName, entityId, format, null, null);
-      } else {
-        Accept acceptType = null;
-        if (StringUtils.isNotBlank(format)) {
-          acceptType = Accept.valueOf(format.toUpperCase());
-        } else if (StringUtils.isNotBlank(accept)) {
-          acceptType = Accept.parse(accept, null);
-        }
-
-        response = xml.createResponse(null, null, null, acceptType, Response.Status.NO_CONTENT);
-      }
-
-      if (StringUtils.isNotBlank(prefer)) {
-        response.getHeaders().put("Preference-Applied", Collections.<Object> singletonList(prefer));
-      }
-
-      return response;
-    } catch (Exception e) {
-      return xml.createFaultResponse(accept, e);
-    }
-  }
-
-  private Response deletePropertyValue(
-      final String accept,
-      final String prefer,
-      final String entitySetName,
-      final String entityId,
-      final String path,
-      final String format) {
-    try {
-      Accept acceptType = null;
-      if (StringUtils.isNotBlank(format)) {
-        acceptType = Accept.valueOf(format.toUpperCase());
-      } else if (StringUtils.isNotBlank(accept)) {
-        acceptType = Accept.parse(accept, null);
-      }
-
-      // if the given path is not about any link then search for property
-      LOG.info("Retrieve property {}", path);
-
-      final AbstractUtilities utils = getUtilities(acceptType);
-
-      final InputStream changed = utils.deleteProperty(
-          entitySetName,
-          entityId,
-          Arrays.asList(path.split("/")),
-          acceptType);
-
-      final Response response;
-      if ("return-content".equalsIgnoreCase(prefer)) {
-        response = xml.createResponse(null, changed, null, acceptType, Response.Status.OK);
-      } else {
-        changed.close();
-        response = xml.createResponse(null, null, null, acceptType, Response.Status.NO_CONTENT);
-      }
-
-      if (StringUtils.isNotBlank(prefer)) {
-        response.getHeaders().put("Preference-Applied", Collections.<Object> singletonList(prefer));
-      }
-
-      return response;
-
-    } catch (Exception e) {
-      return xml.createFaultResponse(accept, e);
-    }
-  }
-
-  /**
-   * Replace property value.
-   *
-   * @param accept
-   * @param entitySetName
-   * @param entityId
-   * @param path
-   * @param format
-   * @param changes
-   * @return response
-   */
-  @PUT
-  @Path("/{entitySetName}({entityId})/{path:.*}/$value")
-  public Response replacePropertyValue(
-      @Context final UriInfo uriInfo,
-      @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept,
-      @HeaderParam("Content-Type") @DefaultValue(StringUtils.EMPTY) final String contentType,
-      @HeaderParam("Prefer") @DefaultValue(StringUtils.EMPTY) final String prefer,
-      @PathParam("entitySetName") final String entitySetName,
-      @PathParam("entityId") final String entityId,
-      @PathParam("path") final String path,
-      @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format,
-      final String changes) {
-
-    return replaceProperty(uriInfo.getRequestUri().toASCIIString(),
-        accept, contentType, prefer, entitySetName, entityId, path, format, changes, true);
-  }
-
-  /**
-   * Replace property.
-   *
-   * @param accept
-   * @param entitySetName
-   * @param entityId
-   * @param path
-   * @param format
-   * @param changes
-   * @return response
-   */
-  @PATCH
-  @Path("/{entitySetName}({entityId})/{path:.*}")
-  public Response patchProperty(
-      @Context final UriInfo uriInfo,
-      @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept,
-      @HeaderParam("Content-Type") @DefaultValue(StringUtils.EMPTY) final String contentType,
-      @HeaderParam("Prefer") @DefaultValue(StringUtils.EMPTY) final String prefer,
-      @PathParam("entitySetName") final String entitySetName,
-      @PathParam("entityId") final String entityId,
-      @PathParam("path") final String path,
-      @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format,
-      final String changes) {
-
-    return replaceProperty(uriInfo.getRequestUri().toASCIIString(),
-        accept, contentType, prefer, entitySetName, entityId, path, format, changes, false);
-  }
-
-  @PUT
-  @Produces({ MediaType.APPLICATION_ATOM_XML, MediaType.APPLICATION_JSON })
-  @Consumes({ MediaType.WILDCARD, MediaType.APPLICATION_OCTET_STREAM })
-  @Path("/{entitySetName}({entityId})/$value")
-  public Response replaceMediaEntity(
-      @Context final UriInfo uriInfo,
-      @HeaderParam("Prefer") @DefaultValue(StringUtils.EMPTY) final String prefer,
-      @PathParam("entitySetName") final String entitySetName,
-      @PathParam("entityId") final String entityId,
-      @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format,
-      final String value) {
-    try {
-
-      final AbstractUtilities utils = getUtilities(null);
-
-      final InputStream res = utils.putMediaInMemory(
-          entitySetName, entityId, IOUtils.toInputStream(value, Constants.ENCODING));
-
-      final String location = uriInfo.getRequestUri().toASCIIString().replace("/$value", "");
-
-      final Response response;
-      if ("return-content".equalsIgnoreCase(prefer)) {
-        response = xml.createResponse(location, res, null, null, Response.Status.OK);
-      } else {
-        res.close();
-        response = xml.createResponse(location, null, null, null, Response.Status.NO_CONTENT);
-      }
-
-      if (StringUtils.isNotBlank(prefer)) {
-        response.getHeaders().put("Preference-Applied", Collections.<Object> singletonList(prefer));
-      }
-
-      return response;
-
-    } catch (Exception e) {
-      LOG.error("Error retrieving entity", e);
-      return xml.createFaultResponse(Accept.JSON.toString(), e);
-    }
-  }
-
-  /**
-   * Replace property.
-   *
-   * @param accept
-   * @param entitySetName
-   * @param entityId
-   * @param path
-   * @param format
-   * @param changes
-   * @return response
-   */
-  @PUT
-  @Path("/{entitySetName}({entityId})/{path:.*}")
-  public Response replaceProperty(
-      @Context final UriInfo uriInfo,
-      @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept,
-      @HeaderParam("Content-Type") @DefaultValue(StringUtils.EMPTY) final String contentType,
-      @HeaderParam("Prefer") @DefaultValue(StringUtils.EMPTY) final String prefer,
-      @PathParam("entitySetName") final String entitySetName,
-      @PathParam("entityId") final String entityId,
-      @PathParam("path") final String path,
-      @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format,
-      final String changes) {
-
-    if (xml.isMediaContent(entitySetName + "/" + path)) {
-      return replaceMediaProperty(prefer, entitySetName, entityId, path, changes);
-    } else {
-      return replaceProperty(uriInfo.getRequestUri().toASCIIString(),
-          accept, contentType, prefer, entitySetName, entityId, path, format, changes, false);
-    }
-  }
-
-  private Response replaceMediaProperty(
-      final String prefer,
-      final String entitySetName,
-      final String entityId,
-      final String path,
-      final String value) {
-
-    try {
-      final AbstractUtilities utils = getUtilities(null);
-
-      InputStream res = utils.putMediaInMemory(
-          entitySetName, entityId, path, IOUtils.toInputStream(value, Constants.ENCODING));
-
-      final Response response;
-      if ("return-content".equalsIgnoreCase(prefer)) {
-        response = xml.createResponse(null, res, null, null, Response.Status.OK);
-      } else {
-        res.close();
-        response = xml.createResponse(null, null, null, null, Response.Status.NO_CONTENT);
-      }
-
-      if (StringUtils.isNotBlank(prefer)) {
-        response.getHeaders().put("Preference-Applied", Collections.<Object> singletonList(prefer));
-      }
-
-      return response;
-    } catch (Exception e) {
-      LOG.error("Error retrieving entity", e);
-      return xml.createFaultResponse(Accept.JSON.toString(), e);
-    }
-  }
-
-  /**
-   * Nullify property value.
-   *
-   * @param accept
-   * @param entitySetName
-   * @param entityId
-   * @param path
-   * @param format
-   * @return response
-   */
-  @DELETE
-  @Path("/{entitySetName}({entityId})/{path:.*}/$value")
-  public Response deleteProperty(
-      @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept,
-      @HeaderParam("Prefer") @DefaultValue(StringUtils.EMPTY) final String prefer,
-      @PathParam("entitySetName") final String entitySetName,
-      @PathParam("entityId") final String entityId,
-      @PathParam("path") final String path,
-      @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format) {
-    return deletePropertyValue(accept, prefer, entitySetName, entityId, path, format);
-  }
-
-  /**
-   * Retrieve property sample.
-   *
-   * @param accept Accept header.
-   * @param entitySetName Entity set name.
-   * @param entityId entity id.
-   * @param path path.
-   * @param format format query option.
-   * @return property.
-   */
-  @GET
-  @Path("/{entitySetName}({entityId})/{path:.*}/$value")
-  public Response getPathValue(
-      @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept,
-      @PathParam("entitySetName") final String entitySetName,
-      @PathParam("entityId") final String entityId,
-      @PathParam("path") final String path,
-      @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format) {
-
-    try {
-      Accept acceptType = null;
-      if (StringUtils.isNotBlank(format)) {
-        acceptType = Accept.valueOf(format.toUpperCase());
-      } else if (StringUtils.isNotBlank(accept)) {
-        acceptType = Accept.parse(accept, null);
-      }
-
-      return navigateProperty(acceptType, entitySetName, entityId, path, true);
-    } catch (Exception e) {
-      return xml.createFaultResponse(accept, e);
-    }
-  }
-
-  /**
-   * Retrieve property sample.
-   *
-   * @param accept Accept header.
-   * @param entitySetName Entity set name.
-   * @param entityId entity id.
-   * @param path path.
-   * @param format format query option.
-   * @return property.
-   */
-  @GET
-  @Path("/{entitySetName}({entityId})/{path:.*}")
-  public Response getPath(
-      @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept,
-      @PathParam("entitySetName") final String entitySetName,
-      @PathParam("entityId") final String entityId,
-      @PathParam("path") final String path,
-      @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format) {
-
-    // default utilities
-    final AbstractUtilities utils = xml;
-
-    try {
-      if (utils.isMediaContent(entitySetName + "/" + path)) {
-        return navigateStreamedEntity(entitySetName, entityId, path);
-      } else {
-        Accept acceptType = null;
-        if (StringUtils.isNotBlank(format)) {
-          acceptType = Accept.valueOf(format.toUpperCase());
-        } else if (StringUtils.isNotBlank(accept)) {
-          acceptType = Accept.parse(accept, null);
-        }
-
-        try {
-          final LinkInfo linkInfo = xml.readLinks(entitySetName, entityId, path, Accept.XML);
-          final Map.Entry<String, List<String>> links = xml.extractLinkURIs(linkInfo.getLinks());
-          final InputStream stream = xml.readEntities(links.getValue(), path, links.getKey(), linkInfo.isFeed());
-
-          final ByteArrayOutputStream content = new ByteArrayOutputStream();
-          final OutputStreamWriter writer = new OutputStreamWriter(content, Constants.ENCODING);
-
-          final ResWrap<?> container = linkInfo.isFeed() ? atomDeserializer.toEntitySet(stream) : atomDeserializer.
-              toEntity(stream);
-          if (acceptType == Accept.ATOM) {
-            atomSerializer.write(writer, container);
-          } else {
-            jsonSerializer.write(writer, container);
-          }
-          writer.flush();
-          writer.close();
-
-          final String basePath = Commons.getEntityBasePath(entitySetName, entityId);
-
-          return xml.createResponse(
-              null,
-              new ByteArrayInputStream(content.toByteArray()),
-              Commons.getETag(basePath),
-              acceptType);
-
-        } catch (NotFoundException e) {
-          // if the given path is not about any link then search for property
-          return navigateProperty(acceptType, entitySetName, entityId, path, false);
-        }
-      }
-    } catch (Exception e) {
-      return utils.createFaultResponse(accept, e);
-    }
-  }
-
-  private Response navigateStreamedEntity(
-      final String entitySetName,
-      final String entityId,
-      final String path) throws Exception {
-
-    final AbstractUtilities utils = getUtilities(null);
-    final Map.Entry<String, InputStream> entityInfo = utils.readMediaEntity(entitySetName, entityId, path);
-    return utils.createResponse(null, entityInfo.getValue(), Commons.getETag(entityInfo.getKey()), null);
-  }
-
-  private Response navigateProperty(
-      final Accept acceptType,
-      final String entitySetName,
-      final String entityId,
-      final String path,
-      final boolean searchForValue) throws Exception {
-
-    if ((searchForValue && acceptType != null && acceptType != Accept.TEXT) || acceptType == Accept.ATOM) {
-      throw new UnsupportedMediaTypeException("Unsupported media type " + acceptType);
-    }
-
-    final AbstractUtilities utils = getUtilities(acceptType);
-
-    final Map.Entry<String, InputStream> entityInfo = utils.readEntity(entitySetName, entityId, Accept.ATOM);
-
-    final InputStream entity = entityInfo.getValue();
-
-    final ResWrap<Entity> entryContainer = atomDeserializer.toEntity(entity);
-
-    final String[] pathElems = StringUtils.split(path, "/");
-    Property property = entryContainer.getPayload().getProperty(pathElems[0]);
-    if (pathElems.length > 1 && property.isComplex()) {
-      for (Property sub : property.asComplex().getValue()) {
-        if (pathElems[1].equals(sub.getName())) {
-          property = sub;
-          if (pathElems.length > 2 && property.isComplex()) {
-            for (Property subsub : property.asComplex().getValue()) {
-              if (pathElems[2].equals(subsub.getName())) {
-                property = subsub;
-              }
-            }
-          }
-        }
-      }
-    }
-
-    final ResWrap<Property> container = new ResWrap<Property>(
-        URI.create(Constants.get(ConstantKey.ODATA_METADATA_PREFIX) + entitySetName + "(" + entityId + ")/" + path),
-        entryContainer.getMetadataETag(),
-        property);
-
-    return xml.createResponse(null,
-        searchForValue ? IOUtils.toInputStream(
-            container.getPayload().isNull() ? StringUtils.EMPTY : stringValue(container.getPayload()),
-                Constants.ENCODING) : utils.writeProperty(acceptType, container),
-                Commons.getETag(Commons.getEntityBasePath(entitySetName, entityId)),
-                acceptType);
-  }
-
-  private String stringValue(final Property property) {
-    EdmPrimitiveTypeKind kind = EdmPrimitiveTypeKind.valueOfFQN(property.getType());
-    try {
-      return EdmPrimitiveTypeFactory.getInstance(kind)
-          .valueToString(property.asPrimitive(), null, null,
-              org.apache.olingo.commons.api.Constants.DEFAULT_PRECISION,
-              org.apache.olingo.commons.api.Constants.DEFAULT_SCALE, null);
-    } catch (final EdmPrimitiveTypeException e) {
-      return property.asPrimitive().toString();
-    }
-  }
-
-  /**
-   * Count sample.
-   *
-   * @param accept Accept header.
-   * @param entitySetName entity set name.
-   * @return count.
-   */
-  @GET
-  @Path("/{entitySetName}/$count")
-  public Response count(
-      @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept,
-      @PathParam("entitySetName") final String entitySetName) {
-    try {
-      final Accept acceptType = Accept.parse(accept, Accept.TEXT);
-
-      if (acceptType != Accept.TEXT) {
-        throw new UnsupportedMediaTypeException("Unsupported type " + accept);
-      }
-
-      int count = xml.countAllElements(entitySetName);
-
-      final Response.ResponseBuilder builder = Response.ok();
-      builder.entity(count);
-
-      return builder.build();
-    } catch (Exception e) {
-      return xml.createFaultResponse(accept, e);
-    }
-  }
-
-  public Map.Entry<Accept, AbstractUtilities> getUtilities(final String accept, final String format) {
-    Accept acceptType;
-    if (StringUtils.isNotBlank(format)) {
-      try {
-        acceptType = Accept.valueOf(format.toUpperCase());
-      } catch (Exception e) {
-        acceptType = Accept.parse(format);
-      }
-    } else {
-      acceptType = Accept.parse(accept);
-    }
-
-    return new AbstractMap.SimpleEntry<Accept, AbstractUtilities>(acceptType, getUtilities(acceptType));
-  }
-
-  protected AbstractUtilities getUtilities(final Accept accept) {
-    final AbstractUtilities utils;
-    if (accept == Accept.XML || accept == Accept.TEXT || accept == Accept.ATOM) {
-      utils = xml;
-    } else {
-      utils = json;
-    }
-
-    return utils;
-  }
-
-  protected void updateInlineEntities(final Entity entity) {
-    final String type = entity.getType();
-    EntityType entityType;
-    Map<String, NavigationProperty> navProperties = Collections.emptyMap();
-    if (type != null && type.length() > 0) {
-      entityType = metadata.getEntityOrComplexType(type);
-      navProperties = entityType.getNavigationPropertyMap();
-    }
-
-    for (Property property : entity.getProperties()) {
-      if (navProperties.containsKey(property.getName())) {
-        Link alink = new Link();
-        alink.setTitle(property.getName());
-        alink.getAnnotations().addAll(property.getAnnotations());
-
-        alink.setType(navProperties.get(property.getName()).isEntitySet()
-            ? Constants.get(ConstantKey.ATOM_LINK_FEED)
-                : Constants.get(ConstantKey.ATOM_LINK_ENTRY));
-
-        alink.setRel(Constants.get(ConstantKey.ATOM_LINK_REL) + property.getName());
-
-        if (property.isCollection()) {
-          EntityCollection inline = new EntityCollection();
-          for (Object value : property.asCollection()) {
-            Entity inlineEntity = new Entity();
-            inlineEntity.setType(navProperties.get(property.getName()).getType());
-            for (Property prop : ((ComplexValue) value).getValue()) {
-              inlineEntity.getProperties().add(prop);
-            }
-            inline.getEntities().add(inlineEntity);
-          }
-          alink.setInlineEntitySet(inline);
-        } else if (property.isComplex()) {
-          Entity inline = new Entity();
-          inline.setType(navProperties.get(property.getName()).getType());
-          for (Property prop : property.asComplex().getValue()) {
-            inline.getProperties().add(prop);
-          }
-          alink.setInlineEntity(inline);
-
-        } else {
-          throw new IllegalStateException("Invalid navigation property " + property);
-        }
-        entity.getNavigationLinks().add(alink);
-      }
-    }
-  }
-
-  protected void normalizeAtomEntry(final Entity entry, final String entitySetName, final String entityKey) {
-    final org.apache.olingo.fit.metadata.EntitySet entitySet = metadata.getEntitySet(entitySetName);
-    final EntityType entityType = metadata.getEntityOrComplexType(entitySet.getType());
-    for (Map.Entry<String, org.apache.olingo.fit.metadata.Property> property : entityType.getPropertyMap().entrySet()) {
-      if (entry.getProperty(property.getKey()) == null && property.getValue().isNullable()) {
-        final Property prop = new Property();
-        prop.setName(property.getKey());
-        prop.setValue(ValueType.PRIMITIVE, null);
-        entry.getProperties().add(prop);
-      }
-    }
-
-    for (Map.Entry<String, NavigationProperty> property : entityType.getNavigationPropertyMap().entrySet()) {
-      boolean found = false;
-      for (Link link : entry.getNavigationLinks()) {
-        if (link.getTitle().equals(property.getKey())) {
-          found = true;
-        }
-      }
-
-      if (!found) {
-        final Link link = new Link();
-        link.setTitle(property.getKey());
-        link.setType(property.getValue().isEntitySet()
-            ? Constants.get(ConstantKey.ATOM_LINK_FEED)
-                : Constants.get(ConstantKey.ATOM_LINK_ENTRY));
-        link.setRel(Constants.get(ConstantKey.ATOM_LINK_REL) + property.getKey());
-        link.setHref(entitySetName + "(" + entityKey + ")/" + property.getKey());
-        entry.getNavigationLinks().add(link);
-      }
-    }
-  }
-}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/fit/src/main/java/org/apache/olingo/fit/Demo.java
----------------------------------------------------------------------
diff --git a/fit/src/main/java/org/apache/olingo/fit/Demo.java b/fit/src/main/java/org/apache/olingo/fit/Demo.java
index c591f01..697b7c9 100644
--- a/fit/src/main/java/org/apache/olingo/fit/Demo.java
+++ b/fit/src/main/java/org/apache/olingo/fit/Demo.java
@@ -40,7 +40,6 @@ import javax.ws.rs.core.UriInfo;
 
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang3.StringUtils;
-import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion;
 import org.apache.olingo.fit.metadata.Metadata;
 import org.apache.olingo.fit.methods.PATCH;
 import org.apache.olingo.fit.utils.Accept;
@@ -54,7 +53,7 @@ import org.springframework.stereotype.Service;
 public class Demo extends Services {
 
   public Demo() throws IOException {
-    super(new Metadata(FSManager.instance(ODataServiceVersion.V40).
+    super(new Metadata(FSManager.instance().
         readRes("demo" + StringUtils.capitalize(Constants.get(ConstantKey.METADATA)), Accept.XML)));
   }
 
@@ -166,9 +165,8 @@ public class Demo extends Services {
       @HeaderParam("Prefer") @DefaultValue(StringUtils.EMPTY) final String prefer,
       @PathParam("entitySetName") final String entitySetName,
       @PathParam("entityId") final String entityId,
-      @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format,
       final String value) {
 
-    return super.replaceMediaEntity(uriInfo, prefer, entitySetName, entityId, format, value);
+    return super.replaceMediaEntity(uriInfo, prefer, entitySetName, entityId, value);
   }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5d7c1287/fit/src/main/java/org/apache/olingo/fit/OpenType.java
----------------------------------------------------------------------
diff --git a/fit/src/main/java/org/apache/olingo/fit/OpenType.java b/fit/src/main/java/org/apache/olingo/fit/OpenType.java
index e65c5bf..a15128e 100644
--- a/fit/src/main/java/org/apache/olingo/fit/OpenType.java
+++ b/fit/src/main/java/org/apache/olingo/fit/OpenType.java
@@ -40,7 +40,6 @@ import javax.ws.rs.core.UriInfo;
 
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang3.StringUtils;
-import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion;
 import org.apache.olingo.fit.metadata.Metadata;
 import org.apache.olingo.fit.utils.Accept;
 import org.apache.olingo.fit.utils.ConstantKey;
@@ -53,8 +52,8 @@ import org.springframework.stereotype.Service;
 public class OpenType extends Services {
 
   public OpenType() throws IOException {
-    super(new Metadata(FSManager.instance(ODataServiceVersion.V40).
-        readRes("openType" + StringUtils.capitalize(Constants.get(ConstantKey.METADATA)), Accept.XML)));
+    super(new Metadata(FSManager.instance()
+        .readRes("openType" + StringUtils.capitalize(Constants.get(ConstantKey.METADATA)), Accept.XML)));
   }
 
   private Response replaceServiceName(final Response response) {


[05/22] olingo-odata4 git commit: [OLINGO-834] better alias support in URI parser

Posted by mi...@apache.org.
[OLINGO-834] better alias support in URI parser

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


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

Branch: refs/heads/OLINGO-832_StreamSerializerPoC
Commit: 110c7b0e5afa1f9f717d95ca48bd5c695821db06
Parents: b317b90
Author: Klaus Straubinger <kl...@sap.com>
Authored: Thu Feb 4 12:24:38 2016 +0100
Committer: Christian Amend <ch...@sap.com>
Committed: Thu Feb 4 12:38:10 2016 +0100

----------------------------------------------------------------------
 .../uri/queryoption/SystemQueryOptionKind.java  |  22 +-
 .../apache/olingo/server/core/ODataHandler.java |   4 +-
 .../server/core/ODataHttpHandlerImpl.java       |  19 +-
 .../olingo/server/core/uri/UriInfoImpl.java     |  37 +-
 .../server/core/uri/parser/ExpandParser.java    |  30 +-
 .../core/uri/parser/ExpressionParser.java       |  85 ++-
 .../server/core/uri/parser/FilterParser.java    |   6 +-
 .../server/core/uri/parser/OrderByParser.java   |   6 +-
 .../olingo/server/core/uri/parser/Parser.java   | 354 +++++++------
 .../server/core/uri/parser/ParserHelper.java    | 168 ++++--
 .../core/uri/parser/ResourcePathParser.java     |  38 +-
 .../server/core/uri/parser/SelectParser.java    |  12 +-
 .../server/core/uri/parser/UriTokenizer.java    |  12 +-
 .../uri/queryoption/expression/AliasImpl.java   |   9 +-
 .../uri/validator/UriValidationException.java   |   4 +-
 .../server/core/uri/validator/UriValidator.java | 513 +++++--------------
 .../server-core-exceptions-i18n.properties      |   1 +
 .../olingo/server/core/uri/UriInfoImplTest.java |  50 +-
 .../core/uri/parser/ExpressionParserTest.java   |   2 +-
 .../core/uri/parser/UriTokenizerTest.java       |   3 +
 .../olingo/server/tecsvc/data/DataProvider.java |  12 +-
 .../SystemQueryOptionsRuntimeException.java     |   3 +-
 .../tecsvc/provider/ContainerProvider.java      |   6 +-
 .../core/uri/parser/TestFullResourcePath.java   | 112 ++--
 .../core/uri/queryoption/QueryOptionTest.java   |   4 +-
 .../queryoption/expression/ExpressionTest.java  |   6 +-
 .../core/uri/testutil/FilterValidator.java      |  51 +-
 .../core/uri/validator/UriValidatorTest.java    |  68 +--
 28 files changed, 797 insertions(+), 840 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/110c7b0e/lib/server-api/src/main/java/org/apache/olingo/server/api/uri/queryoption/SystemQueryOptionKind.java
----------------------------------------------------------------------
diff --git a/lib/server-api/src/main/java/org/apache/olingo/server/api/uri/queryoption/SystemQueryOptionKind.java b/lib/server-api/src/main/java/org/apache/olingo/server/api/uri/queryoption/SystemQueryOptionKind.java
index f0c907b..d5d60a1 100644
--- a/lib/server-api/src/main/java/org/apache/olingo/server/api/uri/queryoption/SystemQueryOptionKind.java
+++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/uri/queryoption/SystemQueryOptionKind.java
@@ -18,10 +18,10 @@
  */
 package org.apache.olingo.server.api.uri.queryoption;
 
+
 /**
  * Defines the supported system query options.
  */
-
 public enum SystemQueryOptionKind {
 
   /**
@@ -84,12 +84,30 @@ public enum SystemQueryOptionKind {
    */
   LEVELS("$levels");
 
-  private String syntax;
+  private final String syntax;
 
   SystemQueryOptionKind(final String syntax) {
     this.syntax = syntax;
   }
 
+  /**
+   * Converts the URI syntax to an enumeration value.
+   * @param option option in the syntax used in the URI
+   * @return system query option kind representing the given option
+   *         (or <code>null</code> if the option does not represent a system query option)
+   */
+  public static SystemQueryOptionKind get(final String option) {
+    for (final SystemQueryOptionKind kind : values()) {
+      if (kind.syntax.equals(option)) {
+        return kind;
+      }
+    }
+    return null;
+  }
+
+  /**
+   * @return URI syntax for this system query option
+   */
   @Override
   public String toString() {
     return syntax;

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/110c7b0e/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandler.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandler.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandler.java
index 96b419c..3baaac7 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandler.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandler.java
@@ -160,6 +160,7 @@ public class ODataHandler {
 
   public void handleException(final ODataRequest request, final ODataResponse response,
       final ODataServerError serverError, final Exception exception) {
+    final int measurementHandle = debugger.startRuntimeMeasurement("ODataHandler", "handleException");
     lastThrownException = exception;
     ErrorProcessor exceptionProcessor;
     try {
@@ -176,8 +177,9 @@ public class ODataHandler {
     } catch (final ContentNegotiatorException e) {
       requestedContentType = ContentType.JSON;
     }
-    final int measurementHandle = debugger.startRuntimeMeasurement("ErrorProcessor", "processError");
+    final int measurementError = debugger.startRuntimeMeasurement("ErrorProcessor", "processError");
     exceptionProcessor.processError(request, response, serverError, requestedContentType);
+    debugger.stopRuntimeMeasurement(measurementError);
     debugger.stopRuntimeMeasurement(measurementHandle);
   }
 

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/110c7b0e/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHttpHandlerImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHttpHandlerImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHttpHandlerImpl.java
index 55c1194..61581c0 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHttpHandlerImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHttpHandlerImpl.java
@@ -24,7 +24,7 @@ import java.nio.channels.Channel;
 import java.nio.channels.Channels;
 import java.nio.channels.ReadableByteChannel;
 import java.nio.channels.WritableByteChannel;
-import java.util.ArrayList;
+import java.util.Collections;
 import java.util.Enumeration;
 import java.util.LinkedHashMap;
 import java.util.List;
@@ -191,8 +191,12 @@ public class ODataHttpHandlerImpl implements ODataHttpHandler {
       odRequest.setBody(httpRequest.getInputStream());
       odRequest.setProtocol(httpRequest.getProtocol());
       odRequest.setMethod(extractMethod(httpRequest));
+      int innerHandle = debugger.startRuntimeMeasurement("ODataHttpHandlerImpl", "copyHeaders");
       copyHeaders(odRequest, httpRequest);
+      debugger.stopRuntimeMeasurement(innerHandle);
+      innerHandle = debugger.startRuntimeMeasurement("ODataHttpHandlerImpl", "fillUriInformation");
       fillUriInformation(odRequest, httpRequest, split);
+      debugger.stopRuntimeMeasurement(innerHandle);
 
       return odRequest;
     } catch (final IOException e) {
@@ -273,14 +277,11 @@ public class ODataHttpHandlerImpl implements ODataHttpHandler {
     odRequest.setRawServiceResolutionUri(rawServiceResolutionUri);
   }
 
-  static void copyHeaders(final ODataRequest odRequest, final HttpServletRequest req) {
-    for (Enumeration<?> headerNames = req.getHeaderNames(); headerNames.hasMoreElements();) {
-      String headerName = (String) headerNames.nextElement();
-      List<String> headerValues = new ArrayList<String>();
-      for (Enumeration<?> headers = req.getHeaders(headerName); headers.hasMoreElements();) {
-        String value = (String) headers.nextElement();
-        headerValues.add(value);
-      }
+  static void copyHeaders(ODataRequest odRequest, final HttpServletRequest req) {
+    for (final Enumeration<?> headerNames = req.getHeaderNames(); headerNames.hasMoreElements();) {
+      final String headerName = (String) headerNames.nextElement();
+      @SuppressWarnings("unchecked") // getHeaders() says it returns an Enumeration of String.
+      final List<String> headerValues = Collections.list(req.getHeaders(headerName));
       odRequest.addHeader(headerName, headerValues);
     }
   }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/110c7b0e/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriInfoImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriInfoImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriInfoImpl.java
index e6fe057..7183bde 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriInfoImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriInfoImpl.java
@@ -20,6 +20,7 @@ package org.apache.olingo.server.core.uri;
 
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.EnumMap;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -64,7 +65,7 @@ public class UriInfoImpl implements UriInfo {
   private List<UriResource> pathParts = new ArrayList<UriResource>();
 
   private Map<SystemQueryOptionKind, SystemQueryOption> systemQueryOptions =
-      new HashMap<SystemQueryOptionKind, SystemQueryOption>();
+      new EnumMap<SystemQueryOptionKind, SystemQueryOption>(SystemQueryOptionKind.class);
   private Map<String, AliasQueryOption> aliases = new HashMap<String, AliasQueryOption>();
   private List<CustomQueryOption> customQueryOptions = new ArrayList<CustomQueryOption>();
 
@@ -155,15 +156,13 @@ public class UriInfoImpl implements UriInfo {
     return Collections.unmodifiableList(pathParts);
   }
 
-  public UriInfoImpl setQueryOptions(final List<QueryOption> list) {
-    for (final QueryOption item : list) {
-      if (item instanceof SystemQueryOption) {
-        setSystemQueryOption((SystemQueryOption) item);
-      } else if (item instanceof AliasQueryOption) {
-        addAlias((AliasQueryOption) item);
-      } else if (item instanceof CustomQueryOption) {
-        addCustomQueryOption((CustomQueryOption) item);
-      }
+  public UriInfoImpl setQueryOption(final QueryOption option) {
+    if (option instanceof SystemQueryOption) {
+      setSystemQueryOption((SystemQueryOption) option);
+    } else if (option instanceof AliasQueryOption) {
+      addAlias((AliasQueryOption) option);
+    } else if (option instanceof CustomQueryOption) {
+      addCustomQueryOption((CustomQueryOption) option);
     }
     return this;
   }
@@ -263,18 +262,22 @@ public class UriInfoImpl implements UriInfo {
   }
 
   public UriInfoImpl addAlias(final AliasQueryOption alias) {
-    aliases.put(alias.getName(), alias);
+    if (aliases.containsKey(alias.getName())) {
+      throw new ODataRuntimeException("Alias " + alias.getName() + " is already there.");
+    } else {
+      aliases.put(alias.getName(), alias);
+    }
     return this;
   }
 
   @Override
   public String getValueForAlias(final String alias) {
-    final AliasQueryOption aliasQueryOption = getAlias(alias);
+    final AliasQueryOption aliasQueryOption = aliases.get(alias);
     return aliasQueryOption == null ? null : aliasQueryOption.getText();
   }
 
-  public AliasQueryOption getAlias(final String key) {
-    return aliases.get(key);
+  public Map<String, AliasQueryOption> getAliasMap() {
+    return Collections.unmodifiableMap(aliases);
   }
 
   @Override
@@ -282,8 +285,10 @@ public class UriInfoImpl implements UriInfo {
     return Collections.unmodifiableList(new ArrayList<AliasQueryOption>(aliases.values()));
   }
 
-  public UriInfoImpl addCustomQueryOption(final CustomQueryOption item) {
-    customQueryOptions.add(item);
+  public UriInfoImpl addCustomQueryOption(final CustomQueryOption option) {
+    if (option.getName() != null && !option.getName().isEmpty()) {
+      customQueryOptions.add(option);
+    }
     return this;
   }
 

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/110c7b0e/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 d8209d8..03750a5 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
@@ -18,6 +18,8 @@
  */
 package org.apache.olingo.server.core.uri.parser;
 
+import java.util.Map;
+
 import org.apache.olingo.commons.api.edm.Edm;
 import org.apache.olingo.commons.api.edm.EdmEntityType;
 import org.apache.olingo.commons.api.edm.EdmNavigationProperty;
@@ -30,6 +32,7 @@ import org.apache.olingo.server.api.OData;
 import org.apache.olingo.server.api.uri.UriInfoKind;
 import org.apache.olingo.server.api.uri.UriResourceNavigation;
 import org.apache.olingo.server.api.uri.UriResourcePartTyped;
+import org.apache.olingo.server.api.uri.queryoption.AliasQueryOption;
 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.LevelsExpandOption;
@@ -53,10 +56,12 @@ public class ExpandParser {
 
   private final Edm edm;
   private final OData odata;
+  private final Map<String, AliasQueryOption> aliases;
 
-  public ExpandParser(final Edm edm, final OData odata) {
+  public ExpandParser(final Edm edm, final OData odata, final Map<String, AliasQueryOption> aliases) {
     this.edm = edm;
     this.odata = odata;
+    this.aliases = aliases;
   }
 
   public ExpandOption parse(UriTokenizer tokenizer, final EdmStructuredType referencedType)
@@ -92,7 +97,7 @@ public class ExpandParser {
         ParserHelper.requireNext(tokenizer, TokenKind.SLASH);
       }
 
-      UriInfoImpl resource = parseExpandPath(tokenizer, referencedType);
+      UriInfoImpl resource = parseExpandPath(tokenizer, referencedType, item);
 
       UriResourcePartTyped lastPart = (UriResourcePartTyped) resource.getLastResourcePart();
 
@@ -156,8 +161,8 @@ public class ExpandParser {
     return null;
   }
 
-  private UriInfoImpl parseExpandPath(UriTokenizer tokenizer, final EdmStructuredType referencedType)
-      throws UriParserException {
+  private UriInfoImpl parseExpandPath(UriTokenizer tokenizer, final EdmStructuredType referencedType,
+      ExpandItemImpl item) throws UriParserException {
     UriInfoImpl resource = new UriInfoImpl().setKind(UriInfoKind.resource);
 
     EdmStructuredType type = referencedType;
@@ -181,10 +186,13 @@ public class ExpandParser {
 
     final EdmNavigationProperty navigationProperty = type.getNavigationProperty(name);
     if (navigationProperty == null) {
-      // TODO: could also have been star after complex property (and maybe type cast)
-      throw new UriParserSemanticException(
-          "Navigation Property '" + name + "' not found in type '" + type.getFullQualifiedName() + "'.",
-          UriParserSemanticException.MessageKeys.EXPRESSION_PROPERTY_NOT_IN_TYPE, type.getName(), name);
+      if (tokenizer.next(TokenKind.STAR)) {
+        item.setIsStar(true);
+      } else {
+        throw new UriParserSemanticException(
+            "Navigation Property '" + name + "' not found in type '" + type.getFullQualifiedName() + "'.",
+            UriParserSemanticException.MessageKeys.EXPRESSION_PROPERTY_NOT_IN_TYPE, type.getName(), name);
+      }
     } else {
       resource.addResourcePart(new UriResourceNavigationPropertyImpl(navigationProperty));
     }
@@ -209,11 +217,11 @@ public class ExpandParser {
 
         } else if (!forRef && !forCount && tokenizer.next(TokenKind.EXPAND)) {
           ParserHelper.requireNext(tokenizer, TokenKind.EQ);
-          systemQueryOption = new ExpandParser(edm, odata).parse(tokenizer, referencedType);
+          systemQueryOption = new ExpandParser(edm, odata, aliases).parse(tokenizer, referencedType);
 
         } else if (tokenizer.next(TokenKind.FILTER)) {
           ParserHelper.requireNext(tokenizer, TokenKind.EQ);
-          systemQueryOption = new FilterParser(edm, odata).parse(tokenizer, referencedType, null);
+          systemQueryOption = new FilterParser(edm, odata).parse(tokenizer, referencedType, null, aliases);
 
         } else if (!forRef && !forCount && tokenizer.next(TokenKind.LEVELS)) {
           ParserHelper.requireNext(tokenizer, TokenKind.EQ);
@@ -221,7 +229,7 @@ public class ExpandParser {
 
         } else if (!forCount && tokenizer.next(TokenKind.ORDERBY)) {
           ParserHelper.requireNext(tokenizer, TokenKind.EQ);
-          systemQueryOption = new OrderByParser(edm, odata).parse(tokenizer, referencedType, null);
+          systemQueryOption = new OrderByParser(edm, odata).parse(tokenizer, referencedType, null, aliases);
 
         } else if (tokenizer.next(TokenKind.SEARCH)) {
           ParserHelper.requireNext(tokenizer, TokenKind.EQ);

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/110c7b0e/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpressionParser.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpressionParser.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpressionParser.java
index 1cf279e..a0ec676 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpressionParser.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpressionParser.java
@@ -24,7 +24,7 @@ import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Deque;
-import java.util.HashMap;
+import java.util.EnumMap;
 import java.util.List;
 import java.util.Map;
 
@@ -53,6 +53,7 @@ import org.apache.olingo.server.api.uri.UriResourceFunction;
 import org.apache.olingo.server.api.uri.UriResourceLambdaVariable;
 import org.apache.olingo.server.api.uri.UriResourceNavigation;
 import org.apache.olingo.server.api.uri.UriResourcePartTyped;
+import org.apache.olingo.server.api.uri.queryoption.AliasQueryOption;
 import org.apache.olingo.server.api.uri.queryoption.expression.Alias;
 import org.apache.olingo.server.api.uri.queryoption.expression.Binary;
 import org.apache.olingo.server.api.uri.queryoption.expression.BinaryOperatorKind;
@@ -96,7 +97,7 @@ import org.apache.olingo.server.core.uri.validator.UriValidationException;
 public class ExpressionParser {
   private static final Map<TokenKind, BinaryOperatorKind> tokenToBinaryOperator;
   static {
-    Map<TokenKind, BinaryOperatorKind> temp = new HashMap<TokenKind, BinaryOperatorKind>();
+    Map<TokenKind, BinaryOperatorKind> temp = new EnumMap<TokenKind, BinaryOperatorKind>(TokenKind.class);
     temp.put(TokenKind.OrOperator, BinaryOperatorKind.OR);
     temp.put(TokenKind.AndOperator, BinaryOperatorKind.AND);
 
@@ -121,7 +122,7 @@ public class ExpressionParser {
   // 'cast' and 'isof' are handled specially.
   private static final Map<TokenKind, MethodKind> tokenToMethod;
   static {
-    Map<TokenKind, MethodKind> temp = new HashMap<TokenKind, MethodKind>();
+    Map<TokenKind, MethodKind> temp = new EnumMap<TokenKind, MethodKind>(TokenKind.class);
     temp.put(TokenKind.CeilingMethod, MethodKind.CEILING);
     temp.put(TokenKind.ConcatMethod, MethodKind.CONCAT);
     temp.put(TokenKind.ContainsMethod, MethodKind.CONTAINS);
@@ -163,6 +164,7 @@ public class ExpressionParser {
   private Deque<UriResourceLambdaVariable> lambdaVariables = new ArrayDeque<UriResourceLambdaVariable>();
   private EdmType referringType;
   private Collection<String> crossjoinEntitySetNames;
+  private Map<String, AliasQueryOption> aliases;
 
   public ExpressionParser(final Edm edm, final OData odata) {
     this.edm = edm;
@@ -170,12 +172,13 @@ public class ExpressionParser {
   }
 
   public Expression parse(UriTokenizer tokenizer, final EdmType referringType,
-      final Collection<String> crossjoinEntitySetNames)
+      final Collection<String> crossjoinEntitySetNames, final Map<String, AliasQueryOption> aliases)
       throws UriParserException, UriValidationException {
     // Initialize tokenizer.
     this.tokenizer = tokenizer;
     this.referringType = referringType;
     this.crossjoinEntitySetNames = crossjoinEntitySetNames;
+    this.aliases = aliases;
 
     return parseExpression();
   }
@@ -339,7 +342,14 @@ public class ExpressionParser {
     }
 
     if (tokenizer.next(TokenKind.ParameterAliasName)) {
-      return new AliasImpl(tokenizer.getText());
+      final String name = tokenizer.getText();
+      if (aliases.containsKey(name)) {
+        return new AliasImpl(name,
+            ParserHelper.parseAliasValue(name, null, true, true, edm, referringType, aliases));
+      } else {
+        throw new UriValidationException("Alias '" + name + "' not found.",
+            UriValidationException.MessageKeys.MISSING_ALIAS, name);
+      }
     }
 
     if (tokenizer.next(TokenKind.jsonArrayOrObject)) {
@@ -360,7 +370,8 @@ public class ExpressionParser {
       return parsePrimitive(nextPrimitive);
     }
 
-    final TokenKind nextMethod = nextMethod();
+    final TokenKind nextMethod =
+        ParserHelper.next(tokenizer, tokenToMethod.keySet().toArray(new TokenKind[tokenToMethod.size()]));
     if (nextMethod != null) {
       return parseMethod(nextMethod);
     }
@@ -630,7 +641,7 @@ public class ExpressionParser {
     } else {
       ParserHelper.requireNext(tokenizer, TokenKind.OPEN);
       final List<UriParameter> keyPredicates =
-          ParserHelper.parseKeyPredicate(tokenizer, entitySet.getEntityType(), null);
+          ParserHelper.parseKeyPredicate(tokenizer, entitySet.getEntityType(), null, edm, referringType, aliases);
       resource = new UriResourceEntitySetImpl(entitySet).setKeyPredicates(keyPredicates);
     }
     uriInfo.addResourcePart(resource);
@@ -777,7 +788,8 @@ public class ExpressionParser {
       final UriResourceNavigationPropertyImpl navigationResource =
           new UriResourceNavigationPropertyImpl((EdmNavigationProperty) property);
       navigationResource.setKeyPredicates(
-          ParserHelper.parseNavigationKeyPredicate(tokenizer, (EdmNavigationProperty) property));
+          ParserHelper.parseNavigationKeyPredicate(tokenizer, (EdmNavigationProperty) property,
+              edm, referringType, aliases));
       uriInfo.addResourcePart(navigationResource);
 
       if (navigationResource.isCollection()) {
@@ -830,13 +842,16 @@ public class ExpressionParser {
       if (lastResource instanceof UriResourceNavigation) {
         ((UriResourceNavigationPropertyImpl) lastResource).setKeyPredicates(
               ParserHelper.parseNavigationKeyPredicate(tokenizer,
-                  ((UriResourceNavigationPropertyImpl) lastResource).getProperty()));
+                  ((UriResourceNavigationPropertyImpl) lastResource).getProperty(), edm, referringType, aliases));
       } else if (lastResource instanceof UriResourceFunction
           && ((UriResourceFunction) lastResource).getType() instanceof EdmEntityType) {
         ((UriResourceFunctionImpl) lastResource).setKeyPredicates(
             ParserHelper.parseKeyPredicate(tokenizer,
                 (EdmEntityType) ((UriResourceFunction) lastResource).getType(),
-                null));
+                null,
+                edm,
+                referringType,
+                aliases));
       } else {
         throw new UriParserSemanticException("Unknown or wrong resource type.",
             UriParserSemanticException.MessageKeys.NOT_IMPLEMENTED, lastResource.toString());
@@ -911,18 +926,21 @@ public class ExpressionParser {
   private void parseFunction(final FullQualifiedName fullQualifiedName, UriInfoImpl uriInfo,
       final EdmType lastType, final boolean lastIsCollection) throws UriParserException, UriValidationException {
 
-    final List<UriParameter> parameters = ParserHelper.parseFunctionParameters(tokenizer, edm, referringType, true);
+    final List<UriParameter> parameters =
+        ParserHelper.parseFunctionParameters(tokenizer, edm, referringType, true, aliases);
     final List<String> parameterNames = ParserHelper.getParameterNames(parameters);
     final EdmFunction boundFunction = edm.getBoundFunction(fullQualifiedName,
         lastType.getFullQualifiedName(), lastIsCollection, parameterNames);
 
     if (boundFunction != null) {
+      ParserHelper.validateFunctionParameters(boundFunction, parameters, edm, referringType, aliases);
       parseFunctionRest(uriInfo, boundFunction, parameters);
       return;
     }
 
     final EdmFunction unboundFunction = edm.getUnboundFunction(fullQualifiedName, parameterNames);
     if (unboundFunction != null) {
+      ParserHelper.validateFunctionParameters(unboundFunction, parameters, edm, referringType, aliases);
       parseFunctionRest(uriInfo, unboundFunction, parameters);
       return;
     }
@@ -934,7 +952,8 @@ public class ExpressionParser {
   private void parseBoundFunction(final FullQualifiedName fullQualifiedName, UriInfoImpl uriInfo,
       final UriResourcePartTyped lastResource) throws UriParserException, UriValidationException {
     final EdmType type = lastResource.getType();
-    final List<UriParameter> parameters = ParserHelper.parseFunctionParameters(tokenizer, edm, referringType, true);
+    final List<UriParameter> parameters =
+        ParserHelper.parseFunctionParameters(tokenizer, edm, referringType, true, aliases);
     final List<String> parameterNames = ParserHelper.getParameterNames(parameters);
     final EdmFunction boundFunction = edm.getBoundFunction(fullQualifiedName,
         type.getFullQualifiedName(), lastResource.isCollection(), parameterNames);
@@ -942,6 +961,7 @@ public class ExpressionParser {
       throw new UriParserSemanticException("Bound function '" + fullQualifiedName + "' not found.",
           UriParserSemanticException.MessageKeys.FUNCTION_NOT_FOUND, fullQualifiedName.getFullQualifiedNameAsString());
     }
+    ParserHelper.validateFunctionParameters(boundFunction, parameters, edm, referringType, aliases);
     parseFunctionRest(uriInfo, boundFunction, parameters);
   }
 
@@ -1010,40 +1030,6 @@ public class ExpressionParser {
     }
   }
 
-  private TokenKind nextMethod() {
-    return ParserHelper.next(tokenizer,
-        TokenKind.CeilingMethod,
-        TokenKind.ConcatMethod,
-        TokenKind.ContainsMethod,
-        TokenKind.DateMethod,
-        TokenKind.DayMethod,
-        TokenKind.EndswithMethod,
-        TokenKind.FloorMethod,
-        TokenKind.FractionalsecondsMethod,
-        TokenKind.GeoDistanceMethod,
-        TokenKind.GeoIntersectsMethod,
-        TokenKind.GeoLengthMethod,
-        TokenKind.HourMethod,
-        TokenKind.IndexofMethod,
-        TokenKind.LengthMethod,
-        TokenKind.MaxdatetimeMethod,
-        TokenKind.MindatetimeMethod,
-        TokenKind.MinuteMethod,
-        TokenKind.MonthMethod,
-        TokenKind.NowMethod,
-        TokenKind.RoundMethod,
-        TokenKind.SecondMethod,
-        TokenKind.StartswithMethod,
-        TokenKind.SubstringMethod,
-        TokenKind.TimeMethod,
-        TokenKind.TolowerMethod,
-        TokenKind.TotaloffsetminutesMethod,
-        TokenKind.TotalsecondsMethod,
-        TokenKind.ToupperMethod,
-        TokenKind.TrimMethod,
-        TokenKind.YearMethod);
-  }
-
   protected static EdmType getType(final Expression expression) throws UriParserException {
     EdmType type;
     if (expression instanceof Literal) {
@@ -1060,11 +1046,12 @@ public class ExpressionParser {
       type = ((BinaryImpl) expression).getType();
     } else if (expression instanceof Method) {
       type = ((MethodImpl) expression).getType();
+    } else if (expression instanceof Alias) {
+      final AliasQueryOption alias = ((AliasImpl) expression).getAlias();
+      type = alias == null || alias.getValue() == null ? null : getType(alias.getValue());
     } else if (expression instanceof LambdaRef) {
       throw new UriParserSemanticException("Type determination not implemented.",
           UriParserSemanticException.MessageKeys.NOT_IMPLEMENTED, expression.toString());
-    } else if (expression instanceof Alias) {
-      type = null; // The alias would have to be available already parsed.
     } else {
       throw new UriParserSemanticException("Unknown expression type.",
           UriParserSemanticException.MessageKeys.NOT_IMPLEMENTED, expression.toString());
@@ -1142,7 +1129,7 @@ public class ExpressionParser {
 
   private Enumeration createEnumExpression(final String primitiveValueLiteral) throws UriParserException {
     final EdmEnumType enumType = getEnumType(primitiveValueLiteral);
-    // TODO: Can the Enumeration interface be changed to handle the value as a whole?
+    // The Enumeration interface could be extended to handle the value as a whole, in line with the primitive type.
     try {
       return new EnumerationImpl(enumType,
           Arrays.asList(enumType.fromUriLiteral(primitiveValueLiteral).split(",")));

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/110c7b0e/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/FilterParser.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/FilterParser.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/FilterParser.java
index dd73009..f20b029 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/FilterParser.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/FilterParser.java
@@ -19,11 +19,13 @@
 package org.apache.olingo.server.core.uri.parser;
 
 import java.util.Collection;
+import java.util.Map;
 
 import org.apache.olingo.commons.api.edm.Edm;
 import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
 import org.apache.olingo.commons.api.edm.EdmType;
 import org.apache.olingo.server.api.OData;
+import org.apache.olingo.server.api.uri.queryoption.AliasQueryOption;
 import org.apache.olingo.server.api.uri.queryoption.FilterOption;
 import org.apache.olingo.server.api.uri.queryoption.expression.Expression;
 import org.apache.olingo.server.core.uri.queryoption.FilterOptionImpl;
@@ -40,10 +42,10 @@ public class FilterParser {
   }
 
   public FilterOption parse(UriTokenizer tokenizer, final EdmType referencedType,
-      final Collection<String> crossjoinEntitySetNames)
+      final Collection<String> crossjoinEntitySetNames, final Map<String, AliasQueryOption> aliases)
       throws UriParserException, UriValidationException {
     final Expression filterExpression = new ExpressionParser(edm, odata)
-        .parse(tokenizer, referencedType, crossjoinEntitySetNames);
+        .parse(tokenizer, referencedType, crossjoinEntitySetNames, aliases);
     final EdmType type = ExpressionParser.getType(filterExpression);
     if (type == null || type.equals(odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Boolean))) {
       return new FilterOptionImpl().setExpression(filterExpression);

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/110c7b0e/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/OrderByParser.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/OrderByParser.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/OrderByParser.java
index 5ea8cb7..b008ed6 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/OrderByParser.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/OrderByParser.java
@@ -19,10 +19,12 @@
 package org.apache.olingo.server.core.uri.parser;
 
 import java.util.Collection;
+import java.util.Map;
 
 import org.apache.olingo.commons.api.edm.Edm;
 import org.apache.olingo.commons.api.edm.EdmStructuredType;
 import org.apache.olingo.server.api.OData;
+import org.apache.olingo.server.api.uri.queryoption.AliasQueryOption;
 import org.apache.olingo.server.api.uri.queryoption.OrderByOption;
 import org.apache.olingo.server.api.uri.queryoption.expression.Expression;
 import org.apache.olingo.server.core.uri.parser.UriTokenizer.TokenKind;
@@ -41,12 +43,12 @@ public class OrderByParser {
   }
 
   public OrderByOption parse(UriTokenizer tokenizer, final EdmStructuredType referencedType,
-      final Collection<String> crossjoinEntitySetNames)
+      final Collection<String> crossjoinEntitySetNames, final Map<String, AliasQueryOption> aliases)
       throws UriParserException, UriValidationException {
     OrderByOptionImpl orderByOption = new OrderByOptionImpl();
     do {
       final Expression orderByExpression = new ExpressionParser(edm, odata)
-          .parse(tokenizer, referencedType, crossjoinEntitySetNames);
+          .parse(tokenizer, referencedType, crossjoinEntitySetNames, aliases);
       OrderByItemImpl item = new OrderByItemImpl();
       item.setExpression(orderByExpression);
       if (tokenizer.next(TokenKind.AscSuffix)) {

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/110c7b0e/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/Parser.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/Parser.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/Parser.java
index 586cb10..e1313c1 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/Parser.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/Parser.java
@@ -20,8 +20,10 @@ package org.apache.olingo.server.core.uri.parser;
 
 import java.util.Collections;
 import java.util.List;
+import java.util.Map;
 
 import org.apache.olingo.commons.api.edm.Edm;
+import org.apache.olingo.commons.api.edm.EdmEntityType;
 import org.apache.olingo.commons.api.edm.EdmStructuredType;
 import org.apache.olingo.commons.api.edm.EdmType;
 import org.apache.olingo.commons.api.ex.ODataRuntimeException;
@@ -36,21 +38,30 @@ import org.apache.olingo.server.api.uri.UriResourcePartTyped;
 import org.apache.olingo.server.api.uri.UriResourceRef;
 import org.apache.olingo.server.api.uri.UriResourceValue;
 import org.apache.olingo.server.api.uri.queryoption.AliasQueryOption;
-import org.apache.olingo.server.api.uri.queryoption.CustomQueryOption;
+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.FilterOption;
+import org.apache.olingo.server.api.uri.queryoption.OrderByItem;
+import org.apache.olingo.server.api.uri.queryoption.OrderByOption;
 import org.apache.olingo.server.api.uri.queryoption.QueryOption;
+import org.apache.olingo.server.api.uri.queryoption.SelectOption;
 import org.apache.olingo.server.api.uri.queryoption.SystemQueryOption;
 import org.apache.olingo.server.api.uri.queryoption.SystemQueryOptionKind;
-import org.apache.olingo.server.api.uri.queryoption.expression.Expression;
 import org.apache.olingo.server.core.uri.UriInfoImpl;
 import org.apache.olingo.server.core.uri.UriResourceStartingTypeFilterImpl;
 import org.apache.olingo.server.core.uri.parser.UriTokenizer.TokenKind;
 import org.apache.olingo.server.core.uri.parser.search.SearchParser;
 import org.apache.olingo.server.core.uri.queryoption.AliasQueryOptionImpl;
 import org.apache.olingo.server.core.uri.queryoption.CountOptionImpl;
+import org.apache.olingo.server.core.uri.queryoption.ExpandOptionImpl;
+import org.apache.olingo.server.core.uri.queryoption.FilterOptionImpl;
 import org.apache.olingo.server.core.uri.queryoption.FormatOptionImpl;
 import org.apache.olingo.server.core.uri.queryoption.IdOptionImpl;
+import org.apache.olingo.server.core.uri.queryoption.OrderByOptionImpl;
+import org.apache.olingo.server.core.uri.queryoption.SelectOptionImpl;
 import org.apache.olingo.server.core.uri.queryoption.SkipOptionImpl;
 import org.apache.olingo.server.core.uri.queryoption.SkipTokenOptionImpl;
+import org.apache.olingo.server.core.uri.queryoption.SystemQueryOptionImpl;
 import org.apache.olingo.server.core.uri.queryoption.TopOptionImpl;
 import org.apache.olingo.server.core.uri.validator.UriValidationException;
 
@@ -74,6 +85,32 @@ public class Parser {
       throws UriParserException, UriValidationException {
 
     UriInfoImpl contextUriInfo = new UriInfoImpl();
+
+    // Read the query options (system and custom options).
+    // This is done before parsing the resource path because the aliases have to be available there.
+    // System query options that can only be parsed with context from the resource path will be post-processed later.
+    final List<QueryOption> options =
+        query == null ? Collections.<QueryOption> emptyList() : UriDecoder.splitAndDecodeOptions(query);
+    for (final QueryOption option : options) {
+      final String optionName = option.getName();
+      // Parse the untyped option and retrieve a system-option or alias-option instance (or null for a custom option).
+      final QueryOption parsedOption = parseOption(optionName, option.getText());
+      try {
+        contextUriInfo.setQueryOption(parsedOption == null ? option : parsedOption);
+      } catch (final ODataRuntimeException e) {
+          throw new UriParserSyntaxException(
+              parsedOption instanceof SystemQueryOption ?
+                  "Double system query option!" :
+                  "Alias already specified! Name: " + optionName,
+              e,
+              parsedOption instanceof SystemQueryOption ?
+                  UriParserSyntaxException.MessageKeys.DOUBLE_SYSTEM_QUERY_OPTION :
+                  UriParserSyntaxException.MessageKeys.DUPLICATED_ALIAS,
+              optionName);
+      }
+    }
+
+    // Read the decoded path segments.
     EdmType contextType = null;
     boolean contextIsCollection = false;
 
@@ -85,7 +122,6 @@ public class Parser {
       numberOfSegments--;
     }
 
-    // first, read the decoded path segments
     final String firstSegment = pathSegmentsDecoded.get(0);
 
     if (firstSegment.isEmpty()) {
@@ -107,24 +143,29 @@ public class Parser {
       contextIsCollection = true;
 
     } else if (firstSegment.equals("$entity")) {
+      contextUriInfo.setKind(UriInfoKind.entityId);
       if (numberOfSegments > 1) {
         final String typeCastSegment = pathSegmentsDecoded.get(1);
         ensureLastSegment(typeCastSegment, 2, numberOfSegments);
-        contextUriInfo = new ResourcePathParser(edm).parseDollarEntityTypeCast(typeCastSegment);
-        contextType = contextUriInfo.getEntityTypeCast();
-      } else {
-        contextUriInfo.setKind(UriInfoKind.entityId);
+        contextType = new ResourcePathParser(edm, contextUriInfo.getAliasMap())
+            .parseDollarEntityTypeCast(typeCastSegment);
+        contextUriInfo.setEntityTypeCast((EdmEntityType) contextType);
       }
       contextIsCollection = false;
 
     } else if (firstSegment.startsWith("$crossjoin")) {
       ensureLastSegment(firstSegment, 1, numberOfSegments);
-      contextUriInfo = new ResourcePathParser(edm).parseCrossjoinSegment(firstSegment);
+      contextUriInfo.setKind(UriInfoKind.crossjoin);
+      final List<String> entitySetNames = new ResourcePathParser(edm, contextUriInfo.getAliasMap())
+          .parseCrossjoinSegment(firstSegment);
+      for (final String name : entitySetNames) {
+        contextUriInfo.addEntitySetName(name);
+      }
       contextIsCollection = true;
 
     } else {
       contextUriInfo.setKind(UriInfoKind.resource);
-      final ResourcePathParser resourcePathParser = new ResourcePathParser(edm);
+      final ResourcePathParser resourcePathParser = new ResourcePathParser(edm, contextUriInfo.getAliasMap());
       int count = 0;
       UriResource lastSegment = null;
       for (final String pathSegment : pathSegmentsDecoded) {
@@ -162,161 +203,168 @@ public class Parser {
       }
     }
 
-    // second, read the system query options and the custom query options
-    final List<QueryOption> options =
-        query == null ? Collections.<QueryOption> emptyList() : UriDecoder.splitAndDecodeOptions(query);
-    for (final QueryOption option : options) {
-      final String optionName = option.getName();
-      final String optionValue = option.getText();
-      if (optionName.startsWith(DOLLAR)) {
-        SystemQueryOption systemOption = null;
-        if (optionName.equals(SystemQueryOptionKind.FILTER.toString())) {
-          UriTokenizer filterTokenizer = new UriTokenizer(optionValue);
-          // The referring type could be a primitive type or a structured type.
-          systemOption = new FilterParser(edm, odata).parse(filterTokenizer,
-              contextType,
-              contextUriInfo.getEntitySetNames());
-          checkOptionEOF(filterTokenizer, optionName, optionValue);
-
-        } else if (optionName.equals(SystemQueryOptionKind.FORMAT.toString())) {
-          FormatOptionImpl formatOption = new FormatOptionImpl();
-          formatOption.setText(optionValue);
-          if (optionValue.equalsIgnoreCase(JSON)
-              || optionValue.equalsIgnoreCase(XML)
-              || optionValue.equalsIgnoreCase(ATOM)
-              || isFormatSyntaxValid(optionValue)) {
-            formatOption.setFormat(optionValue);
-          } else {
-            throw new UriParserSyntaxException("Illegal value of $format option!",
-                UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION_FORMAT, optionValue);
-          }
-          systemOption = formatOption;
-
-        } else if (optionName.equals(SystemQueryOptionKind.EXPAND.toString())) {
-          if (contextType instanceof EdmStructuredType
-              || !contextUriInfo.getEntitySetNames().isEmpty()
-              || contextUriInfo.getKind() == UriInfoKind.all) {
-            UriTokenizer expandTokenizer = new UriTokenizer(optionValue);
-            systemOption = new ExpandParser(edm, odata).parse(expandTokenizer,
-                contextType instanceof EdmStructuredType ? (EdmStructuredType) contextType : null);
-            checkOptionEOF(expandTokenizer, optionName, optionValue);
-          } else {
-            throw new UriValidationException("Expand is only allowed on structured types!",
-                UriValidationException.MessageKeys.SYSTEM_QUERY_OPTION_NOT_ALLOWED, optionName);
-          }
-
-        } else if (optionName.equals(SystemQueryOptionKind.ID.toString())) {
-          IdOptionImpl idOption = new IdOptionImpl();
-          idOption.setText(optionValue);
-          if (optionValue == null || optionValue.isEmpty()) {
-            throw new UriParserSyntaxException("Illegal value of $id option!",
-                UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION,
-                optionName, optionValue);
-          }
-          idOption.setValue(optionValue);
-          systemOption = idOption;
-
-        } else if (optionName.equals(SystemQueryOptionKind.LEVELS.toString())) {
-          throw new UriParserSyntaxException("System query option '$levels' is allowed only inside '$expand'!",
-              UriParserSyntaxException.MessageKeys.SYSTEM_QUERY_OPTION_LEVELS_NOT_ALLOWED_HERE);
-
-        } else if (optionName.equals(SystemQueryOptionKind.ORDERBY.toString())) {
-          UriTokenizer orderByTokenizer = new UriTokenizer(optionValue);
-          systemOption = new OrderByParser(edm, odata).parse(orderByTokenizer,
-              contextType instanceof EdmStructuredType ? (EdmStructuredType) contextType : null,
-              contextUriInfo.getEntitySetNames());
-          checkOptionEOF(orderByTokenizer, optionName, optionValue);
-
-        } else if (optionName.equals(SystemQueryOptionKind.SEARCH.toString())) {
-          systemOption = new SearchParser().parse(optionValue);
-
-        } else if (optionName.equals(SystemQueryOptionKind.SELECT.toString())) {
-          UriTokenizer selectTokenizer = new UriTokenizer(optionValue);
-          systemOption = new SelectParser(edm).parse(selectTokenizer,
-              contextType instanceof EdmStructuredType ? (EdmStructuredType) contextType : null,
-              contextIsCollection);
-          checkOptionEOF(selectTokenizer, optionName, optionValue);
-
-        } else if (optionName.equals(SystemQueryOptionKind.SKIP.toString())) {
-          SkipOptionImpl skipOption = new SkipOptionImpl();
-          skipOption.setText(optionValue);
-          skipOption.setValue(ParserHelper.parseNonNegativeInteger(optionName, optionValue, true));
-          systemOption = skipOption;
+    // Post-process system query options that need context information from the resource path.
+    parseFilterOption(contextUriInfo.getFilterOption(), contextType,
+        contextUriInfo.getEntitySetNames(), contextUriInfo.getAliasMap());
+    parseOrderByOption(contextUriInfo.getOrderByOption(), contextType,
+        contextUriInfo.getEntitySetNames(), contextUriInfo.getAliasMap());
+    parseExpandOption(contextUriInfo.getExpandOption(), contextType,
+        !contextUriInfo.getEntitySetNames().isEmpty() || contextUriInfo.getKind() == UriInfoKind.all,
+        contextUriInfo.getAliasMap());
+    parseSelectOption(contextUriInfo.getSelectOption(), contextType, contextIsCollection);
 
-        } else if (optionName.equals(SystemQueryOptionKind.SKIPTOKEN.toString())) {
-          SkipTokenOptionImpl skipTokenOption = new SkipTokenOptionImpl();
-          skipTokenOption.setText(optionValue);
-          if (optionValue == null || optionValue.isEmpty()) {
-            throw new UriParserSyntaxException("Illegal value of $skiptoken option!",
-                UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION,
-                optionName, optionValue);
-          }
-          skipTokenOption.setValue(optionValue);
-          systemOption = skipTokenOption;
-
-        } else if (optionName.equals(SystemQueryOptionKind.TOP.toString())) {
-          TopOptionImpl topOption = new TopOptionImpl();
-          topOption.setText(optionValue);
-          topOption.setValue(ParserHelper.parseNonNegativeInteger(optionName, optionValue, true));
-          systemOption = topOption;
-
-        } else if (optionName.equals(SystemQueryOptionKind.COUNT.toString())) {
-          CountOptionImpl inlineCountOption = new CountOptionImpl();
-          inlineCountOption.setText(optionValue);
-          if (optionValue.equals("true") || optionValue.equals("false")) {
-            inlineCountOption.setValue(Boolean.parseBoolean(optionValue));
-          } else {
-            throw new UriParserSyntaxException("Illegal value of $count option!",
-                UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION,
-                optionName, optionValue);
-          }
-          systemOption = inlineCountOption;
+    return contextUriInfo;
+  }
 
+  private QueryOption parseOption(final String optionName, final String optionValue)
+      throws UriParserException, UriValidationException {
+    if (optionName.startsWith(DOLLAR)) {
+      final SystemQueryOptionKind kind = SystemQueryOptionKind.get(optionName);
+      if (kind == null) {
+        throw new UriParserSyntaxException("Unknown system query option!",
+            UriParserSyntaxException.MessageKeys.UNKNOWN_SYSTEM_QUERY_OPTION, optionName);
+      }
+      SystemQueryOption systemOption = null;
+      switch (kind) {
+      case SEARCH:
+        systemOption = new SearchParser().parse(optionValue);
+        break;
+      case FILTER:
+        systemOption = new FilterOptionImpl();
+        break;
+      case COUNT:
+        if (optionValue.equals("true") || optionValue.equals("false")) {
+          systemOption = new CountOptionImpl().setValue(Boolean.parseBoolean(optionValue));
         } else {
-          throw new UriParserSyntaxException("Unknown system query option!",
-              UriParserSyntaxException.MessageKeys.UNKNOWN_SYSTEM_QUERY_OPTION, optionName);
+          throw new UriParserSyntaxException("Illegal value of $count option!",
+              UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION,
+              optionName, optionValue);
         }
-        try {
-          contextUriInfo.setSystemQueryOption(systemOption);
-        } catch (final ODataRuntimeException e) {
-          throw new UriParserSyntaxException("Double system query option!", e,
-              UriParserSyntaxException.MessageKeys.DOUBLE_SYSTEM_QUERY_OPTION, optionName);
+        break;
+      case ORDERBY:
+        systemOption = new OrderByOptionImpl();
+        break;
+      case SKIP:
+        systemOption = new SkipOptionImpl()
+            .setValue(ParserHelper.parseNonNegativeInteger(optionName, optionValue, true));
+        break;
+      case SKIPTOKEN:
+        if (optionValue.isEmpty()) {
+          throw new UriParserSyntaxException("Illegal value of $skiptoken option!",
+              UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION,
+              optionName, optionValue);
         }
-
-      } else if (optionName.startsWith(AT)) {
-        if (contextUriInfo.getAlias(optionName) == null) {
-          // TODO: Aliases can only be parsed in the context of their usage.
-          Expression expression = null;
-          UriTokenizer aliasTokenizer = new UriTokenizer(optionValue);
-          if (aliasTokenizer.next(TokenKind.jsonArrayOrObject)) {
-            if (!aliasTokenizer.next(TokenKind.EOF)) {
-              throw new UriParserSyntaxException("Illegal value for alias '" + optionName + "'.",
-                  UriParserSyntaxException.MessageKeys.SYNTAX);
-            }
-          } else {
-            UriTokenizer aliasValueTokenizer = new UriTokenizer(optionValue);
-            expression = new ExpressionParser(edm, odata).parse(aliasValueTokenizer, null,
-                contextUriInfo.getEntitySetNames());
-            if (!aliasValueTokenizer.next(TokenKind.EOF)) {
-              throw new UriParserSyntaxException("Illegal value for alias '" + optionName + "'.",
-                  UriParserSyntaxException.MessageKeys.SYNTAX);
-            }
-          }
-          contextUriInfo.addAlias((AliasQueryOption) new AliasQueryOptionImpl()
-              .setAliasValue(expression)
-              .setName(optionName)
-              .setText(NULL.equals(optionValue) ? null : optionValue));
+        systemOption = new SkipTokenOptionImpl().setValue(optionValue);
+        break;
+      case TOP:
+        systemOption = new TopOptionImpl()
+            .setValue(ParserHelper.parseNonNegativeInteger(optionName, optionValue, true));
+        break;
+      case EXPAND:
+        systemOption = new ExpandOptionImpl();
+        break;
+      case SELECT:
+        systemOption = new SelectOptionImpl();
+        break;
+      case FORMAT:
+        if (optionValue.equalsIgnoreCase(JSON)
+            || optionValue.equalsIgnoreCase(XML)
+            || optionValue.equalsIgnoreCase(ATOM)
+            || isFormatSyntaxValid(optionValue)) {
+          systemOption = new FormatOptionImpl().setFormat(optionValue);
         } else {
-          throw new UriParserSyntaxException("Alias already specified! Name: " + optionName,
-              UriParserSyntaxException.MessageKeys.DUPLICATED_ALIAS, optionName);
+          throw new UriParserSyntaxException("Illegal value of $format option!",
+              UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION_FORMAT, optionValue);
         }
+        break;
+      case ID:
+        if (optionValue.isEmpty()) {
+          throw new UriParserSyntaxException("Illegal value of $id option!",
+              UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION,
+              optionName, optionValue);
+        }
+        systemOption = new IdOptionImpl().setValue(optionValue);
+        break;
+      case LEVELS:
+        throw new UriParserSyntaxException("System query option '$levels' is allowed only inside '$expand'!",
+            UriParserSyntaxException.MessageKeys.SYSTEM_QUERY_OPTION_LEVELS_NOT_ALLOWED_HERE);
+      }
+      ((SystemQueryOptionImpl) systemOption).setText(optionValue);
+      return systemOption;
 
-      } else if (!optionName.isEmpty()) {
-        contextUriInfo.addCustomQueryOption((CustomQueryOption) option);
+    } else if (optionName.startsWith(AT)) {
+      // Aliases can only be parsed in the context of their usage, so the value is not checked here.
+      return new AliasQueryOptionImpl()
+          .setName(optionName)
+          .setText(NULL.equals(optionValue) ? null : optionValue);
+
+    } else {
+      // The option is a custom query option; the caller can re-use its query option.
+      return null;
+    }
+  }
+
+  private void parseFilterOption(FilterOption filterOption, final EdmType contextType,
+      final List<String> entitySetNames, final Map<String, AliasQueryOption> aliases)
+      throws UriParserException, UriValidationException {
+    if (filterOption != null) {
+      final String optionValue = filterOption.getText();
+      UriTokenizer filterTokenizer = new UriTokenizer(optionValue);
+      // The referring type could be a primitive type or a structured type.
+      ((FilterOptionImpl) filterOption).setExpression(
+          new FilterParser(edm, odata).parse(filterTokenizer, contextType, entitySetNames, aliases)
+              .getExpression());
+      checkOptionEOF(filterTokenizer, filterOption.getName(), optionValue);
+    }
+  }
+
+  private void parseOrderByOption(OrderByOption orderByOption, final EdmType contextType,
+      final List<String> entitySetNames, final Map<String, AliasQueryOption> aliases)
+      throws UriParserException, UriValidationException {
+    if (orderByOption != null) {
+      final String optionValue = orderByOption.getText();
+      UriTokenizer orderByTokenizer = new UriTokenizer(optionValue);
+      final OrderByOption option = new OrderByParser(edm, odata).parse(orderByTokenizer,
+          contextType instanceof EdmStructuredType ? (EdmStructuredType) contextType : null,
+          entitySetNames,
+          aliases);
+      checkOptionEOF(orderByTokenizer, orderByOption.getName(), optionValue);
+      for (final OrderByItem item : option.getOrders()) {
+        ((OrderByOptionImpl) orderByOption).addOrder(item);
       }
     }
+  }
 
-    return contextUriInfo;
+  private void parseExpandOption(ExpandOption expandOption, final EdmType contextType, final boolean isCrossjoinOrAll,
+      final Map<String, AliasQueryOption> aliases) throws UriParserException, UriValidationException {
+    if (expandOption != null) {
+      if (!(contextType instanceof EdmStructuredType || isCrossjoinOrAll)) {
+        throw new UriValidationException("Expand is only allowed on structured types!",
+            UriValidationException.MessageKeys.SYSTEM_QUERY_OPTION_NOT_ALLOWED, expandOption.getName());
+      }
+      final String optionValue = expandOption.getText();
+      UriTokenizer expandTokenizer = new UriTokenizer(optionValue);
+      final ExpandOption option = new ExpandParser(edm, odata, aliases).parse(expandTokenizer,
+          contextType instanceof EdmStructuredType ? (EdmStructuredType) contextType : null);
+      checkOptionEOF(expandTokenizer, expandOption.getName(), optionValue);
+      for (final ExpandItem item : option.getExpandItems()) {
+        ((ExpandOptionImpl) expandOption).addExpandItem(item);
+      }
+    }
+  }
+
+  private void parseSelectOption(SelectOption selectOption, final EdmType contextType,
+      final boolean contextIsCollection) throws UriParserException, UriValidationException {
+    if (selectOption != null) {
+      final String optionValue = selectOption.getText();
+      UriTokenizer selectTokenizer = new UriTokenizer(optionValue);
+      ((SelectOptionImpl) selectOption).setSelectItems(
+          new SelectParser(edm).parse(selectTokenizer,
+              contextType instanceof EdmStructuredType ? (EdmStructuredType) contextType : null,
+              contextIsCollection)
+              .getSelectItems());
+      checkOptionEOF(selectTokenizer, selectOption.getName(), optionValue);
+    }
   }
 
   private void ensureLastSegment(final String segment, final int pos, final int size)

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/110c7b0e/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ParserHelper.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ParserHelper.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ParserHelper.java
index b0c2972..9986542 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ParserHelper.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ParserHelper.java
@@ -20,6 +20,7 @@ package org.apache.olingo.server.core.uri.parser;
 
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.EnumMap;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -27,8 +28,10 @@ import java.util.Map.Entry;
 
 import org.apache.olingo.commons.api.edm.Edm;
 import org.apache.olingo.commons.api.edm.EdmEntityType;
+import org.apache.olingo.commons.api.edm.EdmFunction;
 import org.apache.olingo.commons.api.edm.EdmKeyPropertyRef;
 import org.apache.olingo.commons.api.edm.EdmNavigationProperty;
+import org.apache.olingo.commons.api.edm.EdmParameter;
 import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
 import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
 import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
@@ -39,6 +42,7 @@ import org.apache.olingo.commons.api.edm.constants.EdmTypeKind;
 import org.apache.olingo.server.api.OData;
 import org.apache.olingo.server.api.uri.UriParameter;
 import org.apache.olingo.server.api.uri.UriResourcePartTyped;
+import org.apache.olingo.server.api.uri.queryoption.AliasQueryOption;
 import org.apache.olingo.server.api.uri.queryoption.expression.Expression;
 import org.apache.olingo.server.api.uri.queryoption.expression.Literal;
 import org.apache.olingo.server.core.ODataImpl;
@@ -46,6 +50,8 @@ import org.apache.olingo.server.core.uri.UriParameterImpl;
 import org.apache.olingo.server.core.uri.UriResourceTypedImpl;
 import org.apache.olingo.server.core.uri.UriResourceWithKeysImpl;
 import org.apache.olingo.server.core.uri.parser.UriTokenizer.TokenKind;
+import org.apache.olingo.server.core.uri.queryoption.AliasQueryOptionImpl;
+import org.apache.olingo.server.core.uri.queryoption.expression.LiteralImpl;
 import org.apache.olingo.server.core.uri.validator.UriValidationException;
 
 public class ParserHelper {
@@ -55,7 +61,7 @@ public class ParserHelper {
   protected static final Map<TokenKind, EdmPrimitiveTypeKind> tokenToPrimitiveType;
   static {
     /* Enum and null are not present in the map. These have to be handled differently. */
-    Map<TokenKind, EdmPrimitiveTypeKind> temp = new HashMap<TokenKind, EdmPrimitiveTypeKind>();
+    Map<TokenKind, EdmPrimitiveTypeKind> temp = new EnumMap<TokenKind, EdmPrimitiveTypeKind>(TokenKind.class);
     temp.put(TokenKind.BooleanValue, EdmPrimitiveTypeKind.Boolean);
     temp.put(TokenKind.StringValue, EdmPrimitiveTypeKind.String);
     // Very large integer values are of type Edm.Decimal but this is handled elsewhere.
@@ -87,18 +93,18 @@ public class ParserHelper {
     tokenToPrimitiveType = Collections.unmodifiableMap(temp);
   }
 
-  public static void requireNext(UriTokenizer tokenizer, final TokenKind required) throws UriParserException {
+  protected static void requireNext(UriTokenizer tokenizer, final TokenKind required) throws UriParserException {
     if (!tokenizer.next(required)) {
       throw new UriParserSyntaxException("Expected token '" + required.toString() + "' not found.",
           UriParserSyntaxException.MessageKeys.SYNTAX);
     }
   }
 
-  public static void requireTokenEnd(UriTokenizer tokenizer) throws UriParserException {
+  protected static void requireTokenEnd(UriTokenizer tokenizer) throws UriParserException {
     requireNext(tokenizer, TokenKind.EOF);
   }
 
-  public static TokenKind next(UriTokenizer tokenizer, final TokenKind... kinds) {
+  protected static TokenKind next(UriTokenizer tokenizer, final TokenKind... kinds) {
     for (final TokenKind kind : kinds) {
       if (tokenizer.next(kind)) {
         return kind;
@@ -107,7 +113,7 @@ public class ParserHelper {
     return null;
   }
 
-  public static TokenKind nextPrimitiveValue(UriTokenizer tokenizer) {
+  protected static TokenKind nextPrimitiveValue(UriTokenizer tokenizer) {
     return next(tokenizer,
         TokenKind.NULL,
         TokenKind.BooleanValue,
@@ -146,7 +152,8 @@ public class ParserHelper {
   }
 
   protected static List<UriParameter> parseFunctionParameters(UriTokenizer tokenizer,
-      final Edm edm, final EdmType referringType, final boolean withComplex)
+      final Edm edm, final EdmType referringType, final boolean withComplex,
+      final Map<String, AliasQueryOption> aliases)
       throws UriParserException, UriValidationException {
     List<UriParameter> parameters = new ArrayList<UriParameter>();
     ParserHelper.requireNext(tokenizer, TokenKind.OPEN);
@@ -164,40 +171,105 @@ public class ParserHelper {
       if (tokenizer.next(TokenKind.COMMA) || tokenizer.next(TokenKind.CLOSE) || tokenizer.next(TokenKind.EOF)) {
         throw new UriParserSyntaxException("Parameter value expected.", UriParserSyntaxException.MessageKeys.SYNTAX);
       }
+      UriParameterImpl parameter = new UriParameterImpl().setName(name);
       if (tokenizer.next(TokenKind.ParameterAliasName)) {
-        parameters.add(new UriParameterImpl().setName(name).setAlias(tokenizer.getText()));
+        final String aliasName = tokenizer.getText();
+        parameter.setAlias(aliasName)
+            .setExpression(aliases.containsKey(aliasName) ? aliases.get(aliasName).getValue() : null);
       } else if (tokenizer.next(TokenKind.jsonArrayOrObject)) {
         if (withComplex) {
-          parameters.add(new UriParameterImpl().setName(name).setText(tokenizer.getText()));
+          parameter.setText(tokenizer.getText());
         } else {
           throw new UriParserSemanticException("A JSON array or object is not allowed as parameter value.",
               UriParserSemanticException.MessageKeys.COMPLEX_PARAMETER_IN_RESOURCE_PATH, tokenizer.getText());
         }
       } else if (withComplex) {
-        final Expression expression = new ExpressionParser(edm, odata).parse(tokenizer, referringType, null);
-        parameters.add(new UriParameterImpl().setName(name)
-            .setText(expression instanceof Literal ?
-                "null".equals(((Literal) expression).getText()) ? null : ((Literal) expression).getText() :
-                null)
-            .setExpression(expression instanceof Literal ? null : expression));
+        final Expression expression = new ExpressionParser(edm, odata).parse(tokenizer, referringType, null, aliases);
+        parameter.setText(expression instanceof Literal ?
+            "null".equals(((Literal) expression).getText()) ? null : ((Literal) expression).getText() :
+            null)
+            .setExpression(expression instanceof Literal ? null : expression);
       } else if (nextPrimitiveValue(tokenizer) == null) {
         throw new UriParserSemanticException("Wrong parameter value.",
             UriParserSemanticException.MessageKeys.INVALID_KEY_VALUE, "");
       } else {
         final String literalValue = tokenizer.getText();
-        parameters.add(new UriParameterImpl().setName(name)
-            .setText("null".equals(literalValue) ? null : literalValue));
+        parameter.setText("null".equals(literalValue) ? null : literalValue);
       }
+      parameters.add(parameter);
     } while (tokenizer.next(TokenKind.COMMA));
     ParserHelper.requireNext(tokenizer, TokenKind.CLOSE);
     return parameters;
   }
 
+  protected static void validateFunctionParameters(final EdmFunction function, final List<UriParameter> parameters,
+      final Edm edm, final EdmType referringType, final Map<String, AliasQueryOption> aliases)
+      throws UriParserException, UriValidationException {
+    for (final UriParameter parameter : parameters) {
+      final String parameterName = parameter.getName();
+      final EdmParameter edmParameter = function.getParameter(parameterName);
+      final boolean isNullable = edmParameter.isNullable();
+      if (parameter.getText() == null && parameter.getExpression() == null && !isNullable) {
+        if (parameter.getAlias() == null) {
+          // No alias, value is explicitly null.
+          throw new UriValidationException("Missing non-nullable parameter " + parameterName,
+              UriValidationException.MessageKeys.MISSING_PARAMETER, parameterName);
+        } else {
+          final String valueForAlias = aliases.containsKey(parameter.getAlias()) ?
+              parseAliasValue(parameter.getAlias(),
+                  edmParameter.getType(), edmParameter.isNullable(), edmParameter.isCollection(),
+                  edm, referringType, aliases).getText() :
+              null;
+          // Alias value is missing or explicitly null.
+          if (valueForAlias == null) {
+            throw new UriValidationException("Missing alias for " + parameterName,
+                UriValidationException.MessageKeys.MISSING_ALIAS, parameter.getAlias());
+          }
+        }
+      }
+    }
+  }
+
+  protected static AliasQueryOption parseAliasValue(final String name, final EdmType type, final boolean isNullable,
+      final boolean isCollection, final Edm edm, final EdmType referringType,
+      final Map<String, AliasQueryOption> aliases) throws UriParserException, UriValidationException {
+    final EdmTypeKind kind = type == null ? null : type.getKind();
+    final AliasQueryOption alias = aliases.get(name);
+    if (alias != null && alias.getText() != null) {
+      UriTokenizer aliasTokenizer = new UriTokenizer(alias.getText());
+      if (kind == null
+          || !((isCollection || kind == EdmTypeKind.COMPLEX || kind == EdmTypeKind.ENTITY ?
+          aliasTokenizer.next(TokenKind.jsonArrayOrObject) :
+          nextPrimitiveTypeValue(aliasTokenizer, (EdmPrimitiveType) type, isNullable))
+          && aliasTokenizer.next(TokenKind.EOF))) {
+        // The alias value is not an allowed literal value, so parse it again as expression.
+        aliasTokenizer = new UriTokenizer(alias.getText());
+        // Don't pass on the current alias to avoid circular references.
+        Map<String, AliasQueryOption> aliasesInner = new HashMap<String, AliasQueryOption>(aliases);
+        aliasesInner.remove(name);
+        final Expression expression = new ExpressionParser(edm, odata)
+            .parse(aliasTokenizer, referringType, null, aliasesInner);
+        final EdmType expressionType = ExpressionParser.getType(expression);
+        if (aliasTokenizer.next(TokenKind.EOF)
+            && (expressionType == null || type == null || expressionType.equals(type))) {
+          ((AliasQueryOptionImpl) alias).setAliasValue(expression);
+        } else {
+          throw new UriParserSemanticException("Illegal value for alias '" + alias.getName() + "'.",
+              UriParserSemanticException.MessageKeys.UNKNOWN_PART, alias.getText());
+        }
+      }
+    }
+    return alias;
+  }
+
   protected static List<UriParameter> parseNavigationKeyPredicate(UriTokenizer tokenizer,
-      final EdmNavigationProperty navigationProperty) throws UriParserException, UriValidationException {
+      final EdmNavigationProperty navigationProperty,
+      final Edm edm, final EdmType referringType, final Map<String, AliasQueryOption> aliases)
+      throws UriParserException, UriValidationException {
     if (tokenizer.next(TokenKind.OPEN)) {
       if (navigationProperty.isCollection()) {
-        return parseKeyPredicate(tokenizer, navigationProperty.getType(), navigationProperty.getPartner());
+        return parseKeyPredicate(tokenizer, navigationProperty.getType(), navigationProperty.getPartner(),
+            edm, referringType, aliases);
       } else {
         throw new UriParserSemanticException("A key is not allowed on non-collection navigation properties.",
             UriParserSemanticException.MessageKeys.KEY_NOT_ALLOWED);
@@ -207,7 +279,9 @@ public class ParserHelper {
   }
 
   protected static List<UriParameter> parseKeyPredicate(UriTokenizer tokenizer, final EdmEntityType edmEntityType,
-      final EdmNavigationProperty partner) throws UriParserException, UriValidationException {
+      final EdmNavigationProperty partner,
+      final Edm edm, final EdmType referringType, final Map<String, AliasQueryOption> aliases)
+      throws UriParserException, UriValidationException {
     final List<EdmKeyPropertyRef> keyPropertyRefs = edmEntityType.getKeyPropertyRefs();
     if (tokenizer.next(TokenKind.CLOSE)) {
       throw new UriParserSemanticException(
@@ -229,11 +303,11 @@ public class ParserHelper {
     }
 
     if (tokenizer.next(TokenKind.ODataIdentifier)) {
-      keys.addAll(compoundKey(tokenizer, edmEntityType));
+      keys.addAll(compoundKey(tokenizer, edmEntityType, edm, referringType, aliases));
     } else if (keyPropertyRefs.size() - referencedNames.size() == 1) {
       for (final EdmKeyPropertyRef candidate : keyPropertyRefs) {
         if (referencedNames.get(candidate.getName()) == null) {
-          keys.add(simpleKey(tokenizer, candidate));
+          keys.add(simpleKey(tokenizer, candidate, edm, referringType, aliases));
           break;
         }
       }
@@ -271,7 +345,8 @@ public class ParserHelper {
     }
   }
 
-  private static UriParameter simpleKey(UriTokenizer tokenizer, final EdmKeyPropertyRef edmKeyPropertyRef)
+  private static UriParameter simpleKey(UriTokenizer tokenizer, final EdmKeyPropertyRef edmKeyPropertyRef,
+      final Edm edm, final EdmType referringType, final Map<String, AliasQueryOption> aliases)
       throws UriParserException, UriValidationException {
     final EdmProperty edmProperty = edmKeyPropertyRef == null ? null : edmKeyPropertyRef.getProperty();
     if (nextPrimitiveTypeValue(tokenizer,
@@ -279,14 +354,15 @@ public class ParserHelper {
         edmProperty == null ? false : edmProperty.isNullable())) {
       final String literalValue = tokenizer.getText();
       ParserHelper.requireNext(tokenizer, TokenKind.CLOSE);
-      return createUriParameter(edmProperty, edmKeyPropertyRef.getName(), literalValue);
+      return createUriParameter(edmProperty, edmKeyPropertyRef.getName(), literalValue, edm, referringType, aliases);
     } else {
       throw new UriParserSemanticException("The key value is not valid.",
           UriParserSemanticException.MessageKeys.INVALID_KEY_VALUE, edmKeyPropertyRef.getName());
     }
   }
 
-  private static List<UriParameter> compoundKey(UriTokenizer tokenizer, final EdmEntityType edmEntityType)
+  private static List<UriParameter> compoundKey(UriTokenizer tokenizer, final EdmEntityType edmEntityType,
+      final Edm edm, final EdmType referringType, final Map<String, AliasQueryOption> aliases)
       throws UriParserException, UriValidationException {
 
     List<UriParameter> parameters = new ArrayList<UriParameter>();
@@ -312,7 +388,7 @@ public class ParserHelper {
         throw new UriValidationException("Unknown key property " + keyPredicateName,
             UriValidationException.MessageKeys.INVALID_KEY_PROPERTY, keyPredicateName);
       }
-      parameters.add(keyValuePair(tokenizer, keyPredicateName, edmEntityType));
+      parameters.add(keyValuePair(tokenizer, keyPredicateName, edmEntityType, edm, referringType, aliases));
       parameterNames.add(keyPredicateName);
       hasComma = tokenizer.next(TokenKind.COMMA);
       if (hasComma) {
@@ -324,8 +400,9 @@ public class ParserHelper {
     return parameters;
   }
 
-  protected static UriParameter keyValuePair(UriTokenizer tokenizer,
-      final String keyPredicateName, final EdmEntityType edmEntityType)
+  private static UriParameter keyValuePair(UriTokenizer tokenizer,
+      final String keyPredicateName, final EdmEntityType edmEntityType,
+      final Edm edm, final EdmType referringType, final Map<String, AliasQueryOption> aliases)
       throws UriParserException, UriValidationException {
     final EdmKeyPropertyRef keyPropertyRef = edmEntityType.getKeyPropertyRef(keyPredicateName);
     final EdmProperty edmProperty = keyPropertyRef == null ? null : keyPropertyRef.getProperty();
@@ -338,7 +415,7 @@ public class ParserHelper {
       throw new UriParserSyntaxException("Key value expected.", UriParserSyntaxException.MessageKeys.SYNTAX);
     }
     if (nextPrimitiveTypeValue(tokenizer, (EdmPrimitiveType) edmProperty.getType(), edmProperty.isNullable())) {
-      return createUriParameter(edmProperty, keyPredicateName, tokenizer.getText());
+      return createUriParameter(edmProperty, keyPredicateName, tokenizer.getText(), edm, referringType, aliases);
     } else {
       throw new UriParserSemanticException(keyPredicateName + " has not a valid  key value.",
           UriParserSemanticException.MessageKeys.INVALID_KEY_VALUE, keyPredicateName);
@@ -346,28 +423,43 @@ public class ParserHelper {
   }
 
   private static UriParameter createUriParameter(final EdmProperty edmProperty, final String parameterName,
-      final String literalValue) throws UriParserException, UriValidationException {
-    if (literalValue.startsWith("@")) {
-      return new UriParameterImpl()
-          .setName(parameterName)
-          .setAlias(literalValue);
-    }
-
+      final String literalValue, final Edm edm, final EdmType referringType,
+      final Map<String, AliasQueryOption> aliases) throws UriParserException, UriValidationException {
+    final AliasQueryOption alias = literalValue.startsWith("@") ?
+        getKeyAlias(literalValue, edmProperty, edm, referringType, aliases) :
+        null;
+    final String value = alias == null ? literalValue : alias.getText();
     final EdmPrimitiveType primitiveType = (EdmPrimitiveType) edmProperty.getType();
     try {
-      if (!(primitiveType.validate(primitiveType.fromUriLiteral(literalValue), edmProperty.isNullable(),
+      if (!(primitiveType.validate(primitiveType.fromUriLiteral(value), edmProperty.isNullable(),
           edmProperty.getMaxLength(), edmProperty.getPrecision(), edmProperty.getScale(), edmProperty.isUnicode()))) {
         throw new UriValidationException("Invalid key property",
             UriValidationException.MessageKeys.INVALID_KEY_PROPERTY, parameterName);
       }
     } catch (final EdmPrimitiveTypeException e) {
-      throw new UriValidationException("Invalid key property",
+      throw new UriValidationException("Invalid key property", e,
           UriValidationException.MessageKeys.INVALID_KEY_PROPERTY, parameterName);
     }
 
     return new UriParameterImpl()
         .setName(parameterName)
-        .setText("null".equals(literalValue) ? null : literalValue);
+        .setText("null".equals(literalValue) ? null : literalValue)
+        .setAlias(alias == null ? null : literalValue)
+        .setExpression(alias == null ? null :
+            alias.getValue() == null ? new LiteralImpl(value, primitiveType) : alias.getValue());
+  }
+
+  private static AliasQueryOption getKeyAlias(final String name, final EdmProperty edmProperty,
+      final Edm edm, final EdmType referringType, final Map<String, AliasQueryOption> aliases)
+      throws UriParserException, UriValidationException {
+    if (aliases.containsKey(name)) {
+      return parseAliasValue(name,
+          edmProperty.getType(), edmProperty.isNullable(), edmProperty.isCollection(),
+          edm, referringType, aliases);
+    } else {
+      throw new UriValidationException("Alias '" + name + "' for key value not found.",
+          UriValidationException.MessageKeys.MISSING_ALIAS, name);
+    }
   }
 
   private static boolean nextPrimitiveTypeValue(UriTokenizer tokenizer,

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/110c7b0e/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ResourcePathParser.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ResourcePathParser.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ResourcePathParser.java
index 87cb91a..8d6d52d 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ResourcePathParser.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ResourcePathParser.java
@@ -18,7 +18,9 @@
  */
 package org.apache.olingo.server.core.uri.parser;
 
+import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
 
 import org.apache.olingo.commons.api.edm.Edm;
 import org.apache.olingo.commons.api.edm.EdmAction;
@@ -35,11 +37,10 @@ import org.apache.olingo.commons.api.edm.EdmStructuredType;
 import org.apache.olingo.commons.api.edm.EdmType;
 import org.apache.olingo.commons.api.edm.FullQualifiedName;
 import org.apache.olingo.commons.api.edm.constants.EdmTypeKind;
-import org.apache.olingo.server.api.uri.UriInfoKind;
 import org.apache.olingo.server.api.uri.UriParameter;
 import org.apache.olingo.server.api.uri.UriResource;
 import org.apache.olingo.server.api.uri.UriResourcePartTyped;
-import org.apache.olingo.server.core.uri.UriInfoImpl;
+import org.apache.olingo.server.api.uri.queryoption.AliasQueryOption;
 import org.apache.olingo.server.core.uri.UriResourceActionImpl;
 import org.apache.olingo.server.core.uri.UriResourceComplexPropertyImpl;
 import org.apache.olingo.server.core.uri.UriResourceCountImpl;
@@ -59,10 +60,12 @@ public class ResourcePathParser {
 
   private final Edm edm;
   private final EdmEntityContainer edmEntityContainer;
+  private final Map<String, AliasQueryOption> aliases;
   private UriTokenizer tokenizer;
 
-  public ResourcePathParser(final Edm edm) {
+  public ResourcePathParser(final Edm edm, final Map<String, AliasQueryOption> aliases) {
     this.edm = edm;
+    this.aliases = aliases;
     edmEntityContainer = edm.getEntityContainer();
   }
 
@@ -100,8 +103,7 @@ public class ResourcePathParser {
         UriParserSyntaxException.MessageKeys.SYNTAX);
   }
 
-  public UriInfoImpl parseDollarEntityTypeCast(final String pathSegment) throws UriParserException {
-    UriInfoImpl uriInfo = new UriInfoImpl().setKind(UriInfoKind.entityId);
+  public EdmEntityType parseDollarEntityTypeCast(final String pathSegment) throws UriParserException {
     tokenizer = new UriTokenizer(pathSegment);
     ParserHelper.requireNext(tokenizer, TokenKind.QualifiedName);
     final String name = tokenizer.getText();
@@ -110,18 +112,16 @@ public class ResourcePathParser {
     if (type == null) {
       throw new UriParserSemanticException("Type '" + name + "' not found.",
           UriParserSemanticException.MessageKeys.UNKNOWN_TYPE, name);
-    } else {
-      uriInfo.setEntityTypeCast(type);
     }
-    return uriInfo;
+    return type;
   }
 
-  public UriInfoImpl parseCrossjoinSegment(final String pathSegment) throws UriParserException {
-    UriInfoImpl uriInfo = new UriInfoImpl().setKind(UriInfoKind.crossjoin);
+  public List<String> parseCrossjoinSegment(final String pathSegment) throws UriParserException {
     tokenizer = new UriTokenizer(pathSegment);
     ParserHelper.requireNext(tokenizer, TokenKind.CROSSJOIN);
     ParserHelper.requireNext(tokenizer, TokenKind.OPEN);
     // At least one entity-set name is mandatory.  Try to fetch all.
+    List<String> entitySetNames = new ArrayList<String>();
     do {
       ParserHelper.requireNext(tokenizer, TokenKind.ODataIdentifier);
       final String name = tokenizer.getText();
@@ -130,12 +130,12 @@ public class ResourcePathParser {
         throw new UriParserSemanticException("Expected Entity Set Name.",
             UriParserSemanticException.MessageKeys.UNKNOWN_PART, name);
       } else {
-        uriInfo.addEntitySetName(name);
+        entitySetNames.add(name);
       }
     } while (tokenizer.next(TokenKind.COMMA));
     ParserHelper.requireNext(tokenizer, TokenKind.CLOSE);
     ParserHelper.requireTokenEnd(tokenizer);
-    return uriInfo;
+    return entitySetNames;
   }
 
   private UriResource ref(final UriResource previous) throws UriParserException {
@@ -180,7 +180,7 @@ public class ResourcePathParser {
 
       if (tokenizer.next(TokenKind.OPEN)) {
         final List<UriParameter> keyPredicates =
-            ParserHelper.parseKeyPredicate(tokenizer, entitySetResource.getEntityType(), null);
+            ParserHelper.parseKeyPredicate(tokenizer, entitySetResource.getEntityType(), null, edm, null, aliases);
         entitySetResource.setKeyPredicates(keyPredicates);
       }
 
@@ -251,7 +251,8 @@ public class ResourcePathParser {
           UriParserSemanticException.MessageKeys.PROPERTY_NOT_IN_TYPE,
           structType.getFullQualifiedName().getFullQualifiedNameAsString(), name);
     }
-    List<UriParameter> keyPredicate = ParserHelper.parseNavigationKeyPredicate(tokenizer, navigationProperty);
+    List<UriParameter> keyPredicate =
+        ParserHelper.parseNavigationKeyPredicate(tokenizer, navigationProperty, edm, null, aliases);
     ParserHelper.requireTokenEnd(tokenizer);
     return new UriResourceNavigationPropertyImpl(navigationProperty)
         .setKeyPredicates(keyPredicate);
@@ -320,7 +321,8 @@ public class ResourcePathParser {
           ((UriResourceWithKeysImpl) previousTyped).setEntryTypeFilter(type);
         }
         if (tokenizer.next(TokenKind.OPEN)) {
-          final List<UriParameter> keys = ParserHelper.parseKeyPredicate(tokenizer, (EdmEntityType) type, null);
+          final List<UriParameter> keys =
+              ParserHelper.parseKeyPredicate(tokenizer, (EdmEntityType) type, null, edm, null, aliases);
           if (previousTyped.isCollection()) {
             ((UriResourceWithKeysImpl) previousTyped).setKeyPredicates(keys);
           } else {
@@ -359,7 +361,7 @@ public class ResourcePathParser {
   private UriResource functionCall(final EdmFunctionImport edmFunctionImport,
       final FullQualifiedName boundFunctionName, final FullQualifiedName bindingParameterTypeName,
       final boolean isBindingParameterCollection) throws UriParserException, UriValidationException {
-    final List<UriParameter> parameters = ParserHelper.parseFunctionParameters(tokenizer, edm, null, false);
+    final List<UriParameter> parameters = ParserHelper.parseFunctionParameters(tokenizer, edm, null, false, aliases);
     final List<String> names = ParserHelper.getParameterNames(parameters);
     EdmFunction function = null;
     if (edmFunctionImport != null) {
@@ -379,13 +381,15 @@ public class ResourcePathParser {
             UriParserSemanticException.MessageKeys.UNKNOWN_PART, boundFunctionName.getFullQualifiedNameAsString());
       }
     }
+    ParserHelper.validateFunctionParameters(function, parameters, edm, null, aliases);
     UriResourceFunctionImpl resource = new UriResourceFunctionImpl(edmFunctionImport, function, parameters);
     if (tokenizer.next(TokenKind.OPEN)) {
       if (function.getReturnType() != null
           && function.getReturnType().getType().getKind() == EdmTypeKind.ENTITY
           && function.getReturnType().isCollection()) {
         resource.setKeyPredicates(
-            ParserHelper.parseKeyPredicate(tokenizer, (EdmEntityType) function.getReturnType().getType(), null));
+            ParserHelper.parseKeyPredicate(tokenizer,
+                (EdmEntityType) function.getReturnType().getType(), null, edm, null, aliases));
       } else {
         throw new UriParserSemanticException("A key is not allowed.",
             UriParserSemanticException.MessageKeys.KEY_NOT_ALLOWED);

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/110c7b0e/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/SelectParser.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/SelectParser.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/SelectParser.java
index 00f3673..9ec29e3 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/SelectParser.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/SelectParser.java
@@ -123,11 +123,17 @@ public class SelectParser {
   }
 
   private FullQualifiedName parseAllOperationsInSchema(UriTokenizer tokenizer) throws UriParserException {
-    final String name = tokenizer.getText();
+    final String namespace = tokenizer.getText();
     if (tokenizer.next(TokenKind.DOT)) {
       if (tokenizer.next(TokenKind.STAR)) {
-        // TODO: Validate the namespace without loading the whole schema.
-        return new FullQualifiedName(name, tokenizer.getText());
+        // Validate the namespace.  Currently a namespace from a non-default schema is not supported.
+        // There is no direct access to the namespace without loading the whole schema;
+        // however, the default entity container should always be there, so its access methods can be used.
+        if (edm.getEntityContainer(new FullQualifiedName(namespace, edm.getEntityContainer().getName())) == null) {
+          throw new UriParserSemanticException("Wrong namespace '" + namespace + "'.",
+              UriParserSemanticException.MessageKeys.UNKNOWN_PART, namespace);
+        }
+        return new FullQualifiedName(namespace, tokenizer.getText());
       } else {
         throw new UriParserSemanticException("Expected star after dot.",
             UriParserSemanticException.MessageKeys.UNKNOWN_PART, "");

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/110c7b0e/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriTokenizer.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriTokenizer.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriTokenizer.java
index 0504473..d218666 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriTokenizer.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriTokenizer.java
@@ -1311,8 +1311,18 @@ public class UriTokenizer {
         || nextJsonArrayOrObject();
   }
 
+  /**
+   * Moves past a JSON object member if found; otherwise leaves the index unchanged.
+   * @return whether a JSON object member has been found at the current index
+   */
   private boolean nextJsonMember() {
-    return nextJsonString() && nextCharacter(':') && nextJsonValue();
+    final int lastGoodIndex = index;
+    if (nextJsonString() && nextCharacter(':') && nextJsonValue()) {
+      return true;
+    } else {
+      index = lastGoodIndex;
+      return false;
+    }
   }
 
   /**


[16/22] olingo-odata4 git commit: OLINGO-825: Adding the support for odata.type such that the extended entity and complex types are correctly de-serilized

Posted by mi...@apache.org.
OLINGO-825: Adding the support for odata.type such that the extended entity and complex types are correctly de-serilized


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

Branch: refs/heads/OLINGO-832_StreamSerializerPoC
Commit: b7005b774f9172b00ee90773e2f32ed84a9597cd
Parents: 8468308
Author: Ramesh Reddy <ra...@jboss.org>
Authored: Mon Feb 8 15:41:32 2016 -0600
Committer: Ramesh Reddy <ra...@jboss.org>
Committed: Mon Feb 8 15:41:32 2016 -0600

----------------------------------------------------------------------
 .../olingo/fit/tecsvc/client/BasicITCase.java   | 34 ++++----
 .../fit/tecsvc/client/BatchClientITCase.java    |  8 +-
 .../olingo/fit/tecsvc/client/BindingITCase.java | 10 +--
 .../fit/tecsvc/client/DeepInsertITCase.java     | 31 ++++----
 .../tecsvc/client/FilterSystemQueryITCase.java  |  4 +-
 .../org/apache/olingo/server/api/OData.java     | 10 +++
 .../server/core/requests/ActionRequest.java     |  2 +-
 .../server/core/requests/DataRequest.java       |  6 +-
 .../olingo/server/example/TripPinDataModel.java |  2 +-
 .../apache/olingo/server/core/ODataImpl.java    | 13 +++
 .../json/ODataJsonDeserializer.java             | 77 +++++++++++++++++-
 .../deserializer/xml/ODataXmlDeserializer.java  | 84 ++++++++++++++++++--
 .../AbstractODataDeserializerTest.java          |  5 +-
 .../ODataDeserializerEntityCollectionTest.java  |  4 +-
 ...ataJsonDeserializerActionParametersTest.java |  2 +-
 .../json/ODataJsonDeserializerEntityTest.java   | 46 ++++++++++-
 ...DataXMLDeserializerActionParametersTest.java |  2 +-
 .../xml/ODataXmlDeserializerTest.java           | 43 +++++++++-
 18 files changed, 320 insertions(+), 63 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b7005b77/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BasicITCase.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BasicITCase.java b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BasicITCase.java
index c8e4848..a45f548 100644
--- a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BasicITCase.java
+++ b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BasicITCase.java
@@ -391,7 +391,7 @@ public class BasicITCase extends AbstractParamTecSvcITCase {
         getFactory().newPrimitiveValueBuilder().buildString("Test")));
     newEntity.getProperties().add(
         getFactory().newComplexProperty("PropertyCompTwoPrim",
-            getFactory().newComplexValue("CTTwoPrim")
+            getFactory().newComplexValue(SERVICE_NAMESPACE+".CTTwoPrim")
                 .add(getFactory().newPrimitiveProperty(
                     PROPERTY_INT16,
                     getFactory().newPrimitiveValueBuilder().buildInt16((short) 1)))
@@ -537,19 +537,19 @@ public class BasicITCase extends AbstractParamTecSvcITCase {
 
     entity.getProperties().add(
         getFactory().newCollectionProperty("CollPropertyComp",
-            getFactory().newCollectionValue("CTPrimComp")
-                .add(getFactory().newComplexValue("CTPrimComp")
+            getFactory().newCollectionValue(SERVICE_NAMESPACE+".CTPrimComp")
+                .add(getFactory().newComplexValue(SERVICE_NAMESPACE+".CTPrimComp")
                     .add(getFactory().newPrimitiveProperty(PROPERTY_INT16,
                         getFactory().newPrimitiveValueBuilder().buildInt16((short) 42)))
                     .add(getFactory().newComplexProperty(PROPERTY_COMP,
-                        getFactory().newComplexValue("CTAllPrim")
+                        getFactory().newComplexValue(SERVICE_NAMESPACE+".CTAllPrim")
                             .add(getFactory().newPrimitiveProperty(PROPERTY_STRING,
                                 getFactory().newPrimitiveValueBuilder().buildString("42"))))))
-                .add(getFactory().newComplexValue("CTPrimComp")
+                .add(getFactory().newComplexValue(SERVICE_NAMESPACE+".CTPrimComp")
                     .add(getFactory().newPrimitiveProperty(PROPERTY_INT16,
                         getFactory().newPrimitiveValueBuilder().buildInt16((short) 43)))
                     .add(getFactory().newComplexProperty(PROPERTY_COMP,
-                        getFactory().newComplexValue("CTAllPrim")
+                        getFactory().newComplexValue(SERVICE_NAMESPACE+".CTAllPrim")
                             .add(getFactory().newPrimitiveProperty(PROPERTY_STRING,
                                 getFactory().newPrimitiveValueBuilder().buildString("43"))))))));
 
@@ -597,22 +597,24 @@ public class BasicITCase extends AbstractParamTecSvcITCase {
         getFactory().newPrimitiveProperty(PROPERTY_STRING,
             getFactory().newPrimitiveValueBuilder().buildString("Complex collection test")));
     entity.getProperties().add(getFactory().newComplexProperty("PropertyCompTwoPrim",
-        getFactory().newComplexValue("CTTwoPrim")
+        getFactory().newComplexValue(SERVICE_NAMESPACE+".CTTwoPrim")
             .add(getFactory().newPrimitiveProperty(PROPERTY_INT16,
                 getFactory().newPrimitiveValueBuilder().buildInt16((short) 1)))
             .add(getFactory().newPrimitiveProperty(PROPERTY_STRING,
                 getFactory().newPrimitiveValueBuilder().buildString("1")))));
 
     entity.getProperties().add(getFactory().newCollectionProperty("CollPropertyComp",
-        getFactory().newCollectionValue("CTPrimComp")
-            .add(getFactory().newComplexValue("CTPrimComp")
+        getFactory().newCollectionValue(SERVICE_NAMESPACE+".CTPrimComp")
+            .add(getFactory().newComplexValue(SERVICE_NAMESPACE+".CTPrimComp")
                 .add(getFactory().newPrimitiveProperty(PROPERTY_INT16,
                     getFactory().newPrimitiveValueBuilder().buildInt16((short) 1)))
-                .add(getFactory().newComplexProperty(PROPERTY_COMP, getFactory().newComplexValue("CTAllPrim")
+                .add(getFactory().newComplexProperty(PROPERTY_COMP, 
+                    getFactory().newComplexValue(SERVICE_NAMESPACE+".CTAllPrim")
                     .add(getFactory().newPrimitiveProperty(PROPERTY_STRING,
                         getFactory().newPrimitiveValueBuilder().buildString("1"))))))
-            .add(getFactory().newComplexValue("CTPrimComp")
-                .add(getFactory().newComplexProperty(PROPERTY_COMP, getFactory().newComplexValue("CTAllPrim")
+            .add(getFactory().newComplexValue(SERVICE_NAMESPACE+".CTPrimComp")
+                .add(getFactory().newComplexProperty(PROPERTY_COMP, 
+                    getFactory().newComplexValue(SERVICE_NAMESPACE+".CTAllPrim")
                     .add(getFactory().newPrimitiveProperty(PROPERTY_STRING,
                         getFactory().newPrimitiveValueBuilder().buildString("2")))
                     .add(getFactory().newPrimitiveProperty(PROPERTY_INT16,
@@ -789,7 +791,7 @@ public class BasicITCase extends AbstractParamTecSvcITCase {
         factory.newCollectionValue("Edm.String").add(
             factory.newPrimitiveValueBuilder().buildString("Single entry!"))));
     entity.getProperties().add(factory.newComplexProperty(PROPERTY_COMP_ALL_PRIM,
-        factory.newComplexValue("CTAllPrim")
+        factory.newComplexValue(SERVICE_NAMESPACE+".CTAllPrim")
             .add(factory.newPrimitiveProperty(PROPERTY_STRING,
                 factory.newPrimitiveValueBuilder().buildString("Changed")))));
 
@@ -883,7 +885,7 @@ public class BasicITCase extends AbstractParamTecSvcITCase {
         .newPrimitiveValueBuilder()
         .buildString("Must not be null")));
     entity.getProperties().add(factory.newComplexProperty("PropertyCompTwoPrim", factory.newComplexValue
-        ("CTTwoPrim")
+        (SERVICE_NAMESPACE+".CTTwoPrim")
         .add(factory.newPrimitiveProperty(PROPERTY_STRING, factory.newPrimitiveValueBuilder()
             .buildString("Must not be null")))
         .add(factory.newPrimitiveProperty(PROPERTY_INT16,
@@ -892,7 +894,7 @@ public class BasicITCase extends AbstractParamTecSvcITCase {
         factory.newCollectionValue("Edm.String")
             .add(factory.newPrimitiveValueBuilder().buildString("Single entry!"))));
     entity.getProperties().add(factory.newComplexProperty(PROPERTY_COMP_ALL_PRIM,
-        factory.newComplexValue("CTAllPrim").add(
+        factory.newComplexValue(SERVICE_NAMESPACE+".CTAllPrim").add(
             factory.newPrimitiveProperty(PROPERTY_STRING,
                 factory.newPrimitiveValueBuilder().buildString("Changed")))));
 
@@ -1165,7 +1167,7 @@ public class BasicITCase extends AbstractParamTecSvcITCase {
     final ODataPropertyUpdateRequest requestUpdate = getEdmEnabledClient().getCUDRequestFactory()
         .getPropertyComplexValueUpdateRequest(uri, UpdateType.PATCH,
             getFactory().newComplexProperty(PROPERTY_COMP_ALL_PRIM,
-                getFactory().newComplexValue("CTAllPrim")
+                getFactory().newComplexValue(SERVICE_NAMESPACE+".CTAllPrim")
                     .add(getFactory().newPrimitiveProperty(PROPERTY_INT64,
                         getFactory().newPrimitiveValueBuilder().buildInt64(Long.MIN_VALUE)))
                     .add(getFactory().newPrimitiveProperty(PROPERTY_DECIMAL,

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b7005b77/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BatchClientITCase.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BatchClientITCase.java b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BatchClientITCase.java
index 273779c..913d9f9 100644
--- a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BatchClientITCase.java
+++ b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BatchClientITCase.java
@@ -358,7 +358,7 @@ public class BatchClientITCase extends AbstractParamTecSvcITCase {
     final BatchManager streamManager = request.payloadManager();
 
     final ODataChangeset changeset = streamManager.addChangeset();
-    final ClientEntity entityESAllPrim = getFactory().newEntity(new FullQualifiedName(SERVICE_NAMESPACE, "ESAllPrim"));
+    final ClientEntity entityESAllPrim = getFactory().newEntity(new FullQualifiedName(SERVICE_NAMESPACE, "ETAllPrim"));
 
     entityESAllPrim.getProperties().add(getFactory().newPrimitiveProperty("PropertyDouble",
         getFactory().newPrimitiveValueBuilder().buildDouble(3.1415)));
@@ -446,7 +446,7 @@ public class BatchClientITCase extends AbstractParamTecSvcITCase {
     URI editLink = targetURI.build();
 
     ClientObjectFactory factory = getFactory();
-    ClientEntity postEntity = factory.newEntity(new FullQualifiedName(SERVICE_NAMESPACE, "ESAllPrim"));
+    ClientEntity postEntity = factory.newEntity(new FullQualifiedName(SERVICE_NAMESPACE, "ETAllPrim"));
     postEntity.addLink(factory.newEntityNavigationLink("NavPropertyETTwoPrimOne", getClient().newURIBuilder
             (SERVICE_URI)
             .appendEntitySetSegment("ESTwoPrim")
@@ -467,7 +467,7 @@ public class BatchClientITCase extends AbstractParamTecSvcITCase {
     targetURI = getClient().newURIBuilder(SERVICE_URI).appendEntitySetSegment("ESAllPrim").appendKeySegment(0);
     editLink = targetURI.build();
 
-    ClientEntity patchEntity = factory.newEntity(new FullQualifiedName(SERVICE_NAMESPACE, "ESAllPrim"));
+    ClientEntity patchEntity = factory.newEntity(new FullQualifiedName(SERVICE_NAMESPACE, "ETAllPrim"));
     patchEntity.setEditLink(editLink);
 
     patchEntity.getProperties().add(factory.newPrimitiveProperty("PropertyDouble",
@@ -483,7 +483,7 @@ public class BatchClientITCase extends AbstractParamTecSvcITCase {
     targetURI = getClient().newURIBuilder(SERVICE_URI).appendEntitySetSegment("ESAllPrim").appendKeySegment(15);
     editLink = targetURI.build();
 
-    patchEntity = factory.newEntity(new FullQualifiedName(SERVICE_NAMESPACE, "ESAllPrim"));
+    patchEntity = factory.newEntity(new FullQualifiedName(SERVICE_NAMESPACE, "ETAllPrim"));
     patchEntity.setEditLink(editLink);
 
     patchEntity.getProperties().add(factory.newPrimitiveProperty("PropertyDouble",

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b7005b77/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BindingITCase.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BindingITCase.java b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BindingITCase.java
index 25e9c13..9caab23 100644
--- a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BindingITCase.java
+++ b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BindingITCase.java
@@ -50,10 +50,10 @@ public class BindingITCase extends AbstractParamTecSvcITCase {
   private static final String ES_TWO_KEY_NAV = "ESTwoKeyNav";
   private static final String ET_KEY_NAV_NAME = "ETKeyNav";
   private static final FullQualifiedName ET_KEY_NAV = new FullQualifiedName(SERVICE_NAMESPACE, ET_KEY_NAV_NAME);
-  private static final String CT_PRIM_COMP = "CTPrimComp";
-  private static final String CT_TWO_PRIM = "CTTwoPrim";
-  private static final String CT_ALL_PRIM = "CTAllPrim";
-  private static final String CT_NAV_FIVE_PROP = "CTNavFiveProp";
+  private static final String CT_COMP_NAV = SERVICE_NAMESPACE+"."+"CTCompNav";
+  private static final String CT_TWO_PRIM = SERVICE_NAMESPACE+"."+"CTTwoPrim";
+  private static final String CT_ALL_PRIM = SERVICE_NAMESPACE+"."+"CTAllPrim";
+  private static final String CT_NAV_FIVE_PROP = SERVICE_NAMESPACE+"."+"CTNavFiveProp";
   private static final String PROPERTY_INT16 = "PropertyInt16";
   private static final String PROPERTY_STRING = "PropertyString";
   private static final String PROPERTY_COMP_NAV = "PropertyCompNav";
@@ -92,7 +92,7 @@ public class BindingITCase extends AbstractParamTecSvcITCase {
                     42)))
             .add(factory.newPrimitiveProperty(PROPERTY_STRING, factory.newPrimitiveValueBuilder().buildString("42")))));
     entity.getProperties()
-    .add(factory.newComplexProperty(PROPERTY_COMP_COMP_NAV, factory.newComplexValue(CT_PRIM_COMP)
+    .add(factory.newComplexProperty(PROPERTY_COMP_COMP_NAV, factory.newComplexValue(CT_COMP_NAV)
             .add(factory.newPrimitiveProperty(PROPERTY_STRING, factory.newPrimitiveValueBuilder()
                     .buildString("42")))
             .add(factory.newComplexProperty(PROPERTY_COMP_NAV, factory.newComplexValue(CT_NAV_FIVE_PROP)

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b7005b77/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/DeepInsertITCase.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/DeepInsertITCase.java b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/DeepInsertITCase.java
index d8a467a..53cf52c 100644
--- a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/DeepInsertITCase.java
+++ b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/DeepInsertITCase.java
@@ -64,11 +64,12 @@ public class DeepInsertITCase extends AbstractParamTecSvcITCase {
   private static final String ET_TWO_KEY_NAV_NAME = "ETTwoKeyNav";
   private static final FullQualifiedName ET_KEY_NAV = new FullQualifiedName(SERVICE_NAMESPACE, ET_KEY_NAV_NAME);
   private static final FullQualifiedName ET_TWO_KEY_NAV = new FullQualifiedName(SERVICE_NAMESPACE, ET_TWO_KEY_NAV_NAME);
-  private static final String CT_PRIM_COMP = "CTPrimComp";
-  private static final String CT_TWO_PRIM = "CTTwoPrim";
-  private static final String CT_ALL_PRIM = "CTAllPrim";
-  private static final String CT_NAV_FIVE_PROP = "CTNavFiveProp";
-  private static final String CT_BASE_PRIM_COMP_NAV = "CTBasePrimCompNav";
+  private static final String CT_PRIM_COMP = SERVICE_NAMESPACE+"."+"CTPrimComp";
+  private static final String CT_COMP_NAV = SERVICE_NAMESPACE+"."+"CTCompNav";
+  private static final String CT_TWO_PRIM = SERVICE_NAMESPACE+"."+"CTTwoPrim";
+  private static final String CT_ALL_PRIM = SERVICE_NAMESPACE+"."+"CTAllPrim";
+  private static final String CT_NAV_FIVE_PROP = SERVICE_NAMESPACE+"."+"CTNavFiveProp";
+  private static final String CT_BASE_PRIM_COMP_NAV = SERVICE_NAMESPACE+"."+"CTBasePrimCompNav";
   private static final String PROPERTY_INT16 = "PropertyInt16";
   private static final String PROPERTY_STRING = "PropertyString";
   private static final String PROPERTY_COMP = "PropertyComp";
@@ -308,7 +309,7 @@ public class DeepInsertITCase extends AbstractParamTecSvcITCase {
                     factory.newPrimitiveValueBuilder().buildString("42")))));
     entity.getProperties()
         .add(factory.newComplexProperty(PROPERTY_COMP_COMP_NAV,
-            factory.newComplexValue(CT_PRIM_COMP)
+            factory.newComplexValue(CT_COMP_NAV)
                 .add(factory.newPrimitiveProperty(PROPERTY_STRING,
                     factory.newPrimitiveValueBuilder().buildString("42")))
                 .add(factory.newComplexProperty(PROPERTY_COMP_NAV,
@@ -330,7 +331,7 @@ public class DeepInsertITCase extends AbstractParamTecSvcITCase {
                     factory.newPrimitiveValueBuilder().buildInt16((short) 430)))));
     inlineEntitySingle.getProperties()
         .add(factory.newComplexProperty(PROPERTY_COMP_NAV,
-            factory.newComplexValue(CT_PRIM_COMP)
+            factory.newComplexValue(CT_BASE_PRIM_COMP_NAV)
                 .add(factory.newPrimitiveProperty(PROPERTY_INT16,
                     factory.newPrimitiveValueBuilder().buildInt16((short) 431)))));
     inlineEntitySingle.getProperties()
@@ -351,7 +352,7 @@ public class DeepInsertITCase extends AbstractParamTecSvcITCase {
         .add(factory.newPrimitiveProperty(PROPERTY_STRING, factory.newPrimitiveValueBuilder().buildString("44")));
     inlineEntityCol1.getProperties()
         .add(factory.newComplexProperty(PROPERTY_COMP_NAV,
-            factory.newComplexValue(CT_PRIM_COMP)
+            factory.newComplexValue(CT_BASE_PRIM_COMP_NAV)
                 .add(factory.newPrimitiveProperty(PROPERTY_INT16,
                     factory.newPrimitiveValueBuilder().buildInt16((short) 441)))));
     inlineEntityCol1.getProperties()
@@ -374,7 +375,7 @@ public class DeepInsertITCase extends AbstractParamTecSvcITCase {
         .add(factory.newPrimitiveProperty(PROPERTY_STRING, factory.newPrimitiveValueBuilder().buildString("45")));
     inlineEntityCol2.getProperties()
         .add(factory.newComplexProperty(PROPERTY_COMP_NAV,
-            factory.newComplexValue(CT_PRIM_COMP)
+            factory.newComplexValue(CT_BASE_PRIM_COMP_NAV)
                 .add(factory.newPrimitiveProperty(PROPERTY_INT16,
                     factory.newPrimitiveValueBuilder().buildInt16((short) 451)))));
     inlineEntityCol2.getProperties()
@@ -538,7 +539,7 @@ public class DeepInsertITCase extends AbstractParamTecSvcITCase {
                     factory.newPrimitiveValueBuilder().buildString("42")))));
     entity.getProperties()
         .add(factory.newComplexProperty(PROPERTY_COMP_COMP_NAV,
-            factory.newComplexValue(CT_PRIM_COMP)
+            factory.newComplexValue(CT_COMP_NAV)
                 .add(factory.newPrimitiveProperty(PROPERTY_STRING,
                     factory.newPrimitiveValueBuilder().buildString("42")))
                 .add(factory.newComplexProperty(PROPERTY_COMP_NAV,
@@ -580,7 +581,7 @@ public class DeepInsertITCase extends AbstractParamTecSvcITCase {
                     factory.newPrimitiveValueBuilder().buildString("431")))));
     innerEntity.getProperties()
         .add(factory.newComplexProperty(PROPERTY_COMP_COMP_NAV,
-            factory.newComplexValue(CT_PRIM_COMP)
+            factory.newComplexValue(CT_COMP_NAV)
                 .add(factory.newPrimitiveProperty(PROPERTY_STRING,
                     factory.newPrimitiveValueBuilder().buildString("431")))
                 .add(factory.newComplexProperty(PROPERTY_COMP_NAV,
@@ -804,7 +805,7 @@ public class DeepInsertITCase extends AbstractParamTecSvcITCase {
                     factory.newPrimitiveValueBuilder().buildString("42")))));
     entity.getProperties()
         .add(factory.newComplexProperty(PROPERTY_COMP_COMP_NAV,
-            factory.newComplexValue(CT_PRIM_COMP)
+            factory.newComplexValue(CT_COMP_NAV)
                 .add(factory.newPrimitiveProperty(PROPERTY_STRING,
                     factory.newPrimitiveValueBuilder().buildString("42")))
                 .add(factory.newComplexProperty(PROPERTY_COMP_NAV,
@@ -825,7 +826,7 @@ public class DeepInsertITCase extends AbstractParamTecSvcITCase {
                 factory.newPrimitiveValueBuilder().buildInt16((short) 43)))));
     inlineEntitySingle.getProperties()
         .add(factory.newComplexProperty(PROPERTY_COMP_NAV,
-            factory.newComplexValue(CT_PRIM_COMP)
+            factory.newComplexValue(CT_BASE_PRIM_COMP_NAV)
                 .add(factory.newPrimitiveProperty(PROPERTY_INT16,
                     factory.newPrimitiveValueBuilder().buildInt16((short) 431)))));
     inlineEntitySingle.getProperties()
@@ -846,7 +847,7 @@ public class DeepInsertITCase extends AbstractParamTecSvcITCase {
         .add(factory.newPrimitiveProperty(PROPERTY_STRING, factory.newPrimitiveValueBuilder().buildString("44")));
     inlineEntityCol1.getProperties()
         .add(factory.newComplexProperty(PROPERTY_COMP_NAV,
-            factory.newComplexValue(CT_PRIM_COMP)
+            factory.newComplexValue(CT_BASE_PRIM_COMP_NAV)
                 .add(factory.newPrimitiveProperty(PROPERTY_INT16,
                     factory.newPrimitiveValueBuilder().buildInt16((short) 441)))));
     inlineEntityCol1.getProperties()
@@ -871,7 +872,7 @@ public class DeepInsertITCase extends AbstractParamTecSvcITCase {
             factory.newPrimitiveValueBuilder().buildString("45")));
     inlineEntityCol2.getProperties()
         .add(factory.newComplexProperty(PROPERTY_COMP_NAV,
-            factory.newComplexValue(CT_PRIM_COMP)
+            factory.newComplexValue(CT_BASE_PRIM_COMP_NAV)
                 .add(factory.newPrimitiveProperty(PROPERTY_INT16,
                     factory.newPrimitiveValueBuilder().buildInt16((short) 451)))));
     inlineEntityCol2.getProperties()

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b7005b77/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/FilterSystemQueryITCase.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/FilterSystemQueryITCase.java b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/FilterSystemQueryITCase.java
index 6865a65..ca66db5 100644
--- a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/FilterSystemQueryITCase.java
+++ b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/FilterSystemQueryITCase.java
@@ -911,14 +911,14 @@ public class FilterSystemQueryITCase extends AbstractParamTecSvcITCase {
         getFactory().newPrimitiveValueBuilder().buildString("Test")));
     newEntity.getProperties().add(
         getFactory().newComplexProperty("PropertyCompAllPrim",
-            getFactory().newComplexValue("CTAllPrim")
+            getFactory().newComplexValue(SERVICE_NAMESPACE+"."+"CTAllPrim")
             .add(getFactory().newPrimitiveProperty(
                 "PropertyString",
                 getFactory().newPrimitiveValueBuilder().buildString("Test 3")))));
 
     newEntity.getProperties().add(
         getFactory().newComplexProperty("PropertyCompTwoPrim",
-            getFactory().newComplexValue("CTTwoPrim")
+            getFactory().newComplexValue(SERVICE_NAMESPACE+"."+"CTTwoPrim")
             .add(getFactory().newPrimitiveProperty(
                 "PropertyInt16",
                 getFactory().newPrimitiveValueBuilder().buildInt16((short) 1)))

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b7005b77/lib/server-api/src/main/java/org/apache/olingo/server/api/OData.java
----------------------------------------------------------------------
diff --git a/lib/server-api/src/main/java/org/apache/olingo/server/api/OData.java b/lib/server-api/src/main/java/org/apache/olingo/server/api/OData.java
index 8e90c57..26f5f61 100644
--- a/lib/server-api/src/main/java/org/apache/olingo/server/api/OData.java
+++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/OData.java
@@ -132,6 +132,16 @@ public abstract class OData {
   public abstract ODataDeserializer createDeserializer(ContentType contentType) throws DeserializerException;
 
   /**
+   * Creates a new deserializer object for reading content in the specified format.
+   * Deserializers are used in Processor implementations.
+   *
+   * @param contentType any content type supported by Olingo (XML, JSON ...)
+   * @param metadata ServiceMetada of the service
+   */
+  public abstract ODataDeserializer createDeserializer(ContentType contentType,
+      ServiceMetadata metadata) throws DeserializerException;
+  
+  /**
    * Creates a primitive-type instance.
    * @param kind the kind of the primitive type
    * @return an {@link EdmPrimitiveType} instance for the type kind

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b7005b77/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/ActionRequest.java
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/ActionRequest.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/ActionRequest.java
index 9ff4cde..501b110 100644
--- a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/ActionRequest.java
+++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/ActionRequest.java
@@ -145,7 +145,7 @@ public class ActionRequest extends OperationRequest {
   }
   
   public List<Parameter> getParameters() throws DeserializerException {
-    ODataDeserializer deserializer = odata.createDeserializer(getRequestContentType());
+    ODataDeserializer deserializer = odata.createDeserializer(getRequestContentType(), this.serviceMetadata);
     return new ArrayList<Parameter>(deserializer.actionParameters(getPayload(), getAction()).getActionParameters()
         .values());
   }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b7005b77/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/DataRequest.java
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/DataRequest.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/DataRequest.java
index 44c45bf..42fbdea 100644
--- a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/DataRequest.java
+++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/DataRequest.java
@@ -333,7 +333,7 @@ public class DataRequest extends ServiceRequest {
     }
 
     private Entity getEntityFromClient() throws DeserializerException {
-      ODataDeserializer deserializer = odata.createDeserializer(getRequestContentType());
+      ODataDeserializer deserializer = odata.createDeserializer(getRequestContentType(), getServiceMetaData());
       return deserializer.entity(getODataRequest().getBody(), getEntitySet().getEntityType()).getEntity();
     }
 
@@ -460,7 +460,7 @@ public class DataRequest extends ServiceRequest {
     // /odata-json-format-v4.0-errata02-os-complete.html#_Toc403940643
     // The below code reads as property and converts to an URI
     private List<URI> getPayload() throws DeserializerException {
-      ODataDeserializer deserializer = odata.createDeserializer(getRequestContentType());
+      ODataDeserializer deserializer = odata.createDeserializer(getRequestContentType(), getServiceMetaData());
       return deserializer.entityReferences(getODataRequest().getBody()).getEntityReferences();
     }
 
@@ -701,7 +701,7 @@ public class DataRequest extends ServiceRequest {
 
   private org.apache.olingo.commons.api.data.Property getPropertyValueFromClient(
       EdmProperty edmProperty) throws DeserializerException {
-    ODataDeserializer deserializer = odata.createDeserializer(getRequestContentType());
+    ODataDeserializer deserializer = odata.createDeserializer(getRequestContentType(), getServiceMetaData());
     return deserializer.property(getODataRequest().getBody(), edmProperty).getProperty();
   }
   

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b7005b77/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinDataModel.java
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinDataModel.java b/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinDataModel.java
index c58d9ce..562eac0 100644
--- a/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinDataModel.java
+++ b/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinDataModel.java
@@ -116,7 +116,7 @@ public class TripPinDataModel {
 
   private EntityCollection loadEnities(String entitySetName, EdmEntityType type) {
     try {
-      ODataJsonDeserializer deserializer = new ODataJsonDeserializer(ContentType.JSON);
+      ODataJsonDeserializer deserializer = new ODataJsonDeserializer(ContentType.JSON, this.metadata);
 
       EntityCollection set = deserializer.entityCollection(new FileInputStream(new File(
           "src/test/resources/" + entitySetName.toLowerCase() + ".json")), type).getEntityCollection();

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b7005b77/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataImpl.java
index 4c2642c..e5c5437 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataImpl.java
@@ -121,6 +121,19 @@ public class ODataImpl extends OData {
       throw new DeserializerException("Unsupported format: " + contentType.toContentTypeString(),
           DeserializerException.MessageKeys.UNSUPPORTED_FORMAT, contentType.toContentTypeString());
     }
+  }  
+  @Override
+  public ODataDeserializer createDeserializer(final ContentType contentType,
+      ServiceMetadata metadata) throws DeserializerException {
+    if (contentType.isCompatible(ContentType.JSON)) {
+      return new ODataJsonDeserializer(contentType, metadata);
+    } else if (contentType.isCompatible(ContentType.APPLICATION_XML)
+        || contentType.isCompatible(ContentType.APPLICATION_ATOM_XML)) {
+      return new ODataXmlDeserializer(metadata);
+    } else {
+      throw new DeserializerException("Unsupported format: " + contentType.toContentTypeString(),
+          DeserializerException.MessageKeys.UNSUPPORTED_FORMAT, contentType.toContentTypeString());
+    }
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b7005b77/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/json/ODataJsonDeserializer.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/json/ODataJsonDeserializer.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/json/ODataJsonDeserializer.java
index 7bbc4a0..da57309 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/json/ODataJsonDeserializer.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/json/ODataJsonDeserializer.java
@@ -48,10 +48,13 @@ import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
 import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
 import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
 import org.apache.olingo.commons.api.edm.EdmProperty;
+import org.apache.olingo.commons.api.edm.EdmStructuredType;
 import org.apache.olingo.commons.api.edm.EdmType;
 import org.apache.olingo.commons.api.edm.EdmTypeDefinition;
+import org.apache.olingo.commons.api.edm.FullQualifiedName;
 import org.apache.olingo.commons.api.edm.constants.EdmTypeKind;
 import org.apache.olingo.commons.api.format.ContentType;
+import org.apache.olingo.server.api.ServiceMetadata;
 import org.apache.olingo.server.api.deserializer.DeserializerException;
 import org.apache.olingo.server.api.deserializer.DeserializerException.MessageKeys;
 import org.apache.olingo.server.api.deserializer.DeserializerResult;
@@ -76,10 +79,20 @@ public class ODataJsonDeserializer implements ODataDeserializer {
   private static final String ODATA_CONTROL_INFORMATION_PREFIX = "@odata.";
 
   private final boolean isIEEE754Compatible;
+  private ServiceMetadata serviceMetadata;
 
   public ODataJsonDeserializer(final ContentType contentType) {
     isIEEE754Compatible = isODataIEEE754Compatible(contentType);
   }
+  
+  public ODataJsonDeserializer(final ContentType contentType, final ServiceMetadata serviceMetadata) {
+    isIEEE754Compatible = isODataIEEE754Compatible(contentType);
+    this.serviceMetadata = serviceMetadata;
+  }
+  
+  public void setMetadata(ServiceMetadata metadata) {
+    this.serviceMetadata = metadata;
+  }
 
   @Override
   public DeserializerResult entityCollection(final InputStream stream, final EdmEntityType edmEntityType)
@@ -124,7 +137,8 @@ public class ODataJsonDeserializer implements ODataDeserializer {
           throw new DeserializerException("Nested Arrays and primitive values are not allowed for an entity value.",
               DeserializerException.MessageKeys.INVALID_ENTITY);
         }
-        entities.add(consumeEntityNode(edmEntityType, (ObjectNode) arrayElement, expandBuilder));
+        EdmEntityType derivedEdmEntityType = (EdmEntityType)getDerivedType(edmEntityType, arrayElement);
+        entities.add(consumeEntityNode(derivedEdmEntityType, (ObjectNode) arrayElement, expandBuilder));
       }
       return entities;
     } else {
@@ -140,7 +154,9 @@ public class ODataJsonDeserializer implements ODataDeserializer {
       final ObjectNode tree = parseJsonTree(stream);
       final ExpandTreeBuilderImpl expandBuilder = new ExpandTreeBuilderImpl();
 
-      return DeserializerResultImpl.with().entity(consumeEntityNode(edmEntityType, tree, expandBuilder))
+      EdmEntityType derivedEdmEntityType = (EdmEntityType)getDerivedType(edmEntityType, tree);
+
+      return DeserializerResultImpl.with().entity(consumeEntityNode(derivedEdmEntityType, tree, expandBuilder))
           .expandOption(expandBuilder.build())
           .build();
     } catch (final IOException e) {
@@ -257,6 +273,7 @@ public class ODataJsonDeserializer implements ODataDeserializer {
               edmParameter.isNullable(), edmParameter.getMaxLength(),
               edmParameter.getPrecision(), edmParameter.getScale(), true, edmParameter.getMapping(), node);
       parameter.setValue(property.getValueType(), property.getValue());
+      parameter.setType(property.getType());
     }
     return parameter;
   }
@@ -472,7 +489,12 @@ public class ODataJsonDeserializer implements ODataDeserializer {
           value);
       break;
     case COMPLEX:
-      value = readComplexNode(name, type, isNullable, jsonNode);
+      EdmType derivedType = getDerivedType((EdmComplexType) type,
+          jsonNode);
+      property.setType(derivedType.getFullQualifiedName()
+          .getFullQualifiedNameAsString());
+
+      value = readComplexNode(name, derivedType, isNullable, jsonNode);
       property.setValue(ValueType.COMPLEX, value);
       break;
     default:
@@ -808,4 +830,53 @@ public class ODataJsonDeserializer implements ODataDeserializer {
         && Boolean.TRUE.toString().equalsIgnoreCase(
             contentType.getParameter(ContentType.PARAMETER_IEEE754_COMPATIBLE));
   }
+
+  private EdmType getDerivedType(final EdmStructuredType edmType, final JsonNode jsonNode)
+      throws DeserializerException {
+    JsonNode odataTypeNode = jsonNode.get(Constants.JSON_TYPE);
+    if (odataTypeNode != null) {
+      String odataType = odataTypeNode.asText();
+      if (!odataType.isEmpty()) {
+        odataType = odataType.substring(1);
+        
+        if (odataType.equalsIgnoreCase(edmType.getFullQualifiedName().getFullQualifiedNameAsString())) {
+          return edmType;
+        } else if (this.serviceMetadata == null) {
+          throw new DeserializerException(
+              "Failed to resolve Odata type " + odataType + " due to metadata is not available",
+              DeserializerException.MessageKeys.UNKNOWN_CONTENT);
+        }
+        
+        EdmStructuredType currentEdmType = null;
+        if(edmType instanceof EdmEntityType) {
+          currentEdmType = serviceMetadata.getEdm()
+              .getEntityType(new FullQualifiedName(odataType));          
+        } else {
+          currentEdmType = serviceMetadata.getEdm()
+              .getComplexType(new FullQualifiedName(odataType));          
+        }
+        if (!isAssignable(edmType, currentEdmType)) {
+          throw new DeserializerException(
+              "Odata type " + odataType + " not allowed here",
+              DeserializerException.MessageKeys.UNKNOWN_CONTENT);
+        }
+
+        return currentEdmType;
+      }
+    }
+    return edmType;
+  }
+
+  private boolean isAssignable(final EdmStructuredType edmStructuredType,
+      final EdmStructuredType edmStructuredTypeToAssign) {
+    if (edmStructuredTypeToAssign == null) {
+      return false;
+    } else if (edmStructuredType.getFullQualifiedName()
+        .equals(edmStructuredTypeToAssign.getFullQualifiedName())) {
+      return true;
+    } else {
+      return isAssignable(edmStructuredType,
+          edmStructuredTypeToAssign.getBaseType());
+    }
+  }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b7005b77/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/xml/ODataXmlDeserializer.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/xml/ODataXmlDeserializer.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/xml/ODataXmlDeserializer.java
index b556d8e..c8b5f96 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/xml/ODataXmlDeserializer.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/xml/ODataXmlDeserializer.java
@@ -52,10 +52,13 @@ import org.apache.olingo.commons.api.edm.EdmParameter;
 import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
 import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
 import org.apache.olingo.commons.api.edm.EdmProperty;
+import org.apache.olingo.commons.api.edm.EdmStructuredType;
 import org.apache.olingo.commons.api.edm.EdmType;
+import org.apache.olingo.commons.api.edm.FullQualifiedName;
 import org.apache.olingo.commons.api.format.ContentType;
 import org.apache.olingo.commons.core.edm.EdmTypeInfo;
 import org.apache.olingo.commons.core.edm.primitivetype.AbstractGeospatialType;
+import org.apache.olingo.server.api.ServiceMetadata;
 import org.apache.olingo.server.api.deserializer.DeserializerException;
 import org.apache.olingo.server.api.deserializer.DeserializerException.MessageKeys;
 import org.apache.olingo.server.api.deserializer.DeserializerResult;
@@ -75,7 +78,21 @@ public class ODataXmlDeserializer implements ODataDeserializer {
   private static final QName etagQName = new QName(Constants.NS_METADATA, Constants.ATOM_ATTR_ETAG);
   private static final QName countQName = new QName(Constants.NS_METADATA, Constants.ATOM_ELEM_COUNT);
   private static final QName parametersQName = new QName(Constants.NS_METADATA, "parameters");
+  private static final QName typeQName = new QName(Constants.NS_METADATA, Constants.ATTR_TYPE);
+  
+  private ServiceMetadata serviceMetadata;
 
+  public ODataXmlDeserializer() {
+  }
+
+  public ODataXmlDeserializer(final ServiceMetadata serviceMetadata) {
+    this.serviceMetadata = serviceMetadata;
+  }
+  
+  public void setMetadata(ServiceMetadata metadata) {
+    this.serviceMetadata = metadata;
+  }
+  
   protected XMLEventReader getReader(final InputStream input) throws XMLStreamException {
     return FACTORY.createXMLEventReader(input);
   }
@@ -178,7 +195,17 @@ public class ODataXmlDeserializer implements ODataDeserializer {
     } else {
       property.setName(start.getName().getLocalPart());
     }
-    valuable(property, reader, start, edmType, isNullable, maxLength, precision, scale, isUnicode, isCollection);
+    
+    EdmType resolvedType = edmType;
+    final Attribute attrType = start.getAttributeByName(typeQName);
+    if (attrType != null && (edmType instanceof EdmComplexType)) {
+      String type = new EdmTypeInfo.Builder().setTypeExpression(attrType.getValue()).build().internal();
+      if (type.startsWith("Collection(") && type.endsWith(")")) {
+        type = type.substring(11, type.length()-1);
+      }
+      resolvedType = getDerivedType((EdmComplexType)edmType, type);
+    }
+    valuable(property, reader, start, resolvedType, isNullable, maxLength, precision, scale, isUnicode, isCollection);
     return property;
   }
 
@@ -431,6 +458,7 @@ public class ODataXmlDeserializer implements ODataDeserializer {
   private Entity entity(final XMLEventReader reader, final StartElement start, final EdmEntityType edmEntityType)
       throws XMLStreamException, EdmPrimitiveTypeException, DeserializerException {
     Entity entity = null;
+    EdmEntityType resolvedType = edmEntityType;
     if (entryRefQName.equals(start.getName())) {
       entity = entityRef(start);
     } else if (Constants.QNAME_ATOM_ELEM_ENTRY.equals(start.getName())) {
@@ -455,7 +483,9 @@ public class ODataXmlDeserializer implements ODataDeserializer {
           } else if (Constants.QNAME_ATOM_ELEM_CATEGORY.equals(event.asStartElement().getName())) {
             final Attribute term = event.asStartElement().getAttributeByName(QName.valueOf(Constants.ATOM_ATTR_TERM));
             if (term != null) {
-              entity.setType(new EdmTypeInfo.Builder().setTypeExpression(term.getValue()).build().internal());
+              String type = new EdmTypeInfo.Builder().setTypeExpression(term.getValue()).build().internal();
+              entity.setType(type);
+              resolvedType = (EdmEntityType)getDerivedType(edmEntityType, type);
             }
           } else if (Constants.QNAME_ATOM_ELEM_LINK.equals(event.asStartElement().getName())) {
             final Link link = new Link();
@@ -485,7 +515,7 @@ public class ODataXmlDeserializer implements ODataDeserializer {
                 entity.setMediaETag(mediaETag.getValue());
               }
             } else if (link.getRel().startsWith(Constants.NS_NAVIGATION_LINK_REL)) {
-              inline(reader, event.asStartElement(), link, edmEntityType);
+              inline(reader, event.asStartElement(), link, resolvedType);
               if (link.getInlineEntity() == null && link.getInlineEntitySet() == null) {
                 entity.getNavigationBindings().add(link);
               } else {
@@ -525,7 +555,7 @@ public class ODataXmlDeserializer implements ODataDeserializer {
                 .getAttributeByName(QName.valueOf(Constants.ATTR_TYPE));
             if (contenttype == null || ContentType.APPLICATION_XML.toContentTypeString()
                 .equals(contenttype.getValue())) {
-              properties(reader, skipBeforeFirstStartElement(reader), entity, edmEntityType);
+              properties(reader, skipBeforeFirstStartElement(reader), entity, resolvedType);
             } else {
               entity.setMediaContentType(contenttype.getValue());
               final Attribute src = event.asStartElement().getAttributeByName(QName.valueOf(Constants.ATOM_ATTR_SRC));
@@ -534,7 +564,7 @@ public class ODataXmlDeserializer implements ODataDeserializer {
               }
             }
           } else if (propertiesQName.equals(event.asStartElement().getName())) {
-            properties(reader, event.asStartElement(), entity, edmEntityType);
+            properties(reader, event.asStartElement(), entity, resolvedType);
           }
         }
 
@@ -799,4 +829,48 @@ public class ODataXmlDeserializer implements ODataDeserializer {
     }
     return parameter;
   }
+  
+  private EdmType getDerivedType(final EdmStructuredType edmType, String odataType)
+      throws DeserializerException {
+    if (odataType != null && !odataType.isEmpty()) {
+      
+      if (odataType.equalsIgnoreCase(edmType.getFullQualifiedName().getFullQualifiedNameAsString())) {
+        return edmType;
+      } else if (this.serviceMetadata == null) {
+        throw new DeserializerException(
+            "Failed to resolve Odata type " + odataType + " due to metadata is not available",
+            DeserializerException.MessageKeys.UNKNOWN_CONTENT);
+      }
+      
+      EdmStructuredType currentEdmType = null;
+      if(edmType instanceof EdmEntityType) {
+        currentEdmType = serviceMetadata.getEdm()
+            .getEntityType(new FullQualifiedName(odataType));          
+      } else {
+        currentEdmType = serviceMetadata.getEdm()
+            .getComplexType(new FullQualifiedName(odataType));          
+      }
+      if (!isAssignable(edmType, currentEdmType)) {
+        throw new DeserializerException(
+            "Odata type " + odataType + " not allowed here",
+            DeserializerException.MessageKeys.UNKNOWN_CONTENT);
+      }
+
+      return currentEdmType;
+    }
+    return edmType;
+  }
+
+  private boolean isAssignable(final EdmStructuredType edmStructuredType,
+      final EdmStructuredType edmStructuredTypeToAssign) {
+    if (edmStructuredTypeToAssign == null) {
+      return false;
+    } else if (edmStructuredType.getFullQualifiedName()
+        .equals(edmStructuredTypeToAssign.getFullQualifiedName())) {
+      return true;
+    } else {
+      return isAssignable(edmStructuredType,
+          edmStructuredTypeToAssign.getBaseType());
+    }
+  }  
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b7005b77/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/AbstractODataDeserializerTest.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/AbstractODataDeserializerTest.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/AbstractODataDeserializerTest.java
index c90ad6d..49c4ac9 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/AbstractODataDeserializerTest.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/AbstractODataDeserializerTest.java
@@ -24,6 +24,7 @@ import java.util.Collections;
 
 import org.apache.olingo.commons.api.edm.Edm;
 import org.apache.olingo.server.api.OData;
+import org.apache.olingo.server.api.ServiceMetadata;
 import org.apache.olingo.server.api.edmx.EdmxReference;
 import org.apache.olingo.server.tecsvc.provider.EdmTechProvider;
 
@@ -33,7 +34,9 @@ public class AbstractODataDeserializerTest {
   protected static final Edm edm = OData.newInstance()
       .createServiceMetadata(new EdmTechProvider(), Collections.<EdmxReference> emptyList())
       .getEdm();
-
+  protected static final ServiceMetadata metadata = OData.newInstance()
+      .createServiceMetadata(new EdmTechProvider(), Collections.<EdmxReference> emptyList());
+  
   protected InputStream getFileAsStream(final String filename) throws IOException {
     InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream(filename);
     if (in == null) {

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b7005b77/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/json/ODataDeserializerEntityCollectionTest.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/json/ODataDeserializerEntityCollectionTest.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/json/ODataDeserializerEntityCollectionTest.java
index 4b2c6c3..db65c78 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/json/ODataDeserializerEntityCollectionTest.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/json/ODataDeserializerEntityCollectionTest.java
@@ -165,14 +165,14 @@ public class ODataDeserializerEntityCollectionTest extends AbstractODataDeserial
 
   private EntityCollection deserialize(final InputStream stream, final String entityTypeName)
       throws DeserializerException {
-    return OData.newInstance().createDeserializer(ContentType.JSON)
+    return OData.newInstance().createDeserializer(ContentType.JSON, metadata)
         .entityCollection(stream, edm.getEntityType(new FullQualifiedName(NAMESPACE, entityTypeName)))
         .getEntityCollection();
   }
 
   private EntityCollection deserialize(final String input, final String entityTypeName)
       throws DeserializerException {
-    return OData.newInstance().createDeserializer(ContentType.JSON)
+    return OData.newInstance().createDeserializer(ContentType.JSON, metadata)
         .entityCollection(new ByteArrayInputStream(input.getBytes()),
             edm.getEntityType(new FullQualifiedName(NAMESPACE, entityTypeName)))
         .getEntityCollection();

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b7005b77/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/json/ODataJsonDeserializerActionParametersTest.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/json/ODataJsonDeserializerActionParametersTest.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/json/ODataJsonDeserializerActionParametersTest.java
index 20d4fa2..b1f020e 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/json/ODataJsonDeserializerActionParametersTest.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/json/ODataJsonDeserializerActionParametersTest.java
@@ -254,7 +254,7 @@ public class ODataJsonDeserializerActionParametersTest extends AbstractODataDese
 
   private Map<String, Parameter> deserialize(final String input, final String actionName, final String bindingTypeName)
       throws DeserializerException {
-    return OData.newInstance().createDeserializer(ContentType.JSON)
+    return OData.newInstance().createDeserializer(ContentType.JSON, metadata)
         .actionParameters(new ByteArrayInputStream(input.getBytes()),
             bindingTypeName == null ?
                 edm.getUnboundAction(new FullQualifiedName(NAMESPACE, actionName)) :

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b7005b77/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/json/ODataJsonDeserializerEntityTest.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/json/ODataJsonDeserializerEntityTest.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/json/ODataJsonDeserializerEntityTest.java
index 01e61f3..48dc870 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/json/ODataJsonDeserializerEntityTest.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/json/ODataJsonDeserializerEntityTest.java
@@ -46,10 +46,12 @@ import org.apache.olingo.commons.api.edm.EdmProperty;
 import org.apache.olingo.commons.api.edm.FullQualifiedName;
 import org.apache.olingo.commons.api.edm.provider.CsdlMapping;
 import org.apache.olingo.commons.api.format.ContentType;
+import org.apache.olingo.commons.core.edm.primitivetype.EdmDate;
 import org.apache.olingo.server.api.OData;
 import org.apache.olingo.server.api.deserializer.DeserializerException;
 import org.apache.olingo.server.api.deserializer.ODataDeserializer;
 import org.apache.olingo.server.core.deserializer.AbstractODataDeserializerTest;
+import org.junit.Assert;
 import org.junit.Test;
 
 public class ODataJsonDeserializerEntityTest extends AbstractODataDeserializerTest {
@@ -218,6 +220,46 @@ public class ODataJsonDeserializerEntityTest extends AbstractODataDeserializerTe
   }
 
   @Test
+  public void extendedComplexProperty() throws Exception {
+    
+    final String payload = "{"
+        + "\"@odata.context\":\"$metadata#ESCompComp/$entity\","
+        + "\"@odata.metadataEtag\":\"W/\\\"metadataETag\\\"\","
+        + "\"@odata.etag\":\"W/\\\"32767\\\"\","
+        + "\"PropertyInt16\":32767,"
+        + "\"PropertyComp\":{"
+        + "\"@odata.type\":\"#olingo.odata.test1.CTCompCompExtended\","
+        +   "\"PropertyComp\":{"
+        +   "\"@odata.type\":\"#olingo.odata.test1.CTTwoPrim\","
+        +   "\"PropertyInt16\":32767,"
+        +   "\"PropertyString\":\"First Resource - first\""
+        +   "},"
+        +   "\"PropertyDate\":\"2012-10-03\""
+        + "}}";
+    final Entity result = deserialize(payload, "ETCompComp");
+    
+    Assert.assertNotNull(result);
+    Property property = result.getProperty("PropertyComp");
+    Assert.assertEquals("PropertyComp", property.getName());    
+    Assert.assertTrue(property.isComplex());
+    final ComplexValue cv = property.asComplex();
+    Assert.assertEquals("olingo.odata.test1.CTCompCompExtended", property.getType());
+    Assert.assertEquals(
+        "2012-10-03",
+        EdmDate.getInstance().valueToString(getCVProperty(cv, "PropertyDate").asPrimitive(), false, 10, 3, 0,
+        false));
+  }  
+  
+  private Property getCVProperty(ComplexValue cv, String name) {
+    for (Property p : cv.getValue()) {
+      if (p.getName().equals(name)) {
+        return p;
+      }
+    }
+    return null;
+  }
+  
+  @Test
   public void simpleEntityETCollAllPrim() throws Exception {
     final String entityString = "{"
         + "\"PropertyInt16\":1,"
@@ -606,7 +648,7 @@ public class ODataJsonDeserializerEntityTest extends AbstractODataDeserializerTe
         "{\"PropertyDate\":\"2012-12-03\","
             + "\"PropertyDateTimeOffset\":\"2012-12-03T07:16:23Z\"}";
     InputStream stream = new ByteArrayInputStream(entityString.getBytes());
-    ODataDeserializer deserializer = OData.newInstance().createDeserializer(ContentType.JSON);
+    ODataDeserializer deserializer = OData.newInstance().createDeserializer(ContentType.JSON, metadata);
     Entity entity = deserializer.entity(stream, entityType).getEntity();
     assertNotNull(entity);
     List<Property> properties = entity.getProperties();
@@ -1272,7 +1314,7 @@ public class ODataJsonDeserializerEntityTest extends AbstractODataDeserializerTe
 
   protected static Entity deserialize(final InputStream stream, final String entityTypeName,
       final ContentType contentType) throws DeserializerException {
-    return OData.newInstance().createDeserializer(contentType)
+    return OData.newInstance().createDeserializer(contentType, metadata)
         .entity(stream, edm.getEntityType(new FullQualifiedName(NAMESPACE, entityTypeName)))
         .getEntity();
   }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b7005b77/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/xml/ODataXMLDeserializerActionParametersTest.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/xml/ODataXMLDeserializerActionParametersTest.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/xml/ODataXMLDeserializerActionParametersTest.java
index 18162da..539b70f 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/xml/ODataXMLDeserializerActionParametersTest.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/xml/ODataXMLDeserializerActionParametersTest.java
@@ -234,7 +234,7 @@ public class ODataXMLDeserializerActionParametersTest extends AbstractODataDeser
 
   private Map<String, Parameter> deserialize(final String input, final String actionName, final String bindingTypeName)
       throws DeserializerException {
-    return OData.newInstance().createDeserializer(ContentType.APPLICATION_XML)
+    return OData.newInstance().createDeserializer(ContentType.APPLICATION_XML, metadata)
         .actionParameters(new ByteArrayInputStream(input.getBytes()),
             bindingTypeName == null ?
                 edm.getUnboundAction(new FullQualifiedName(NAMESPACE, actionName)) :

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b7005b77/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/xml/ODataXmlDeserializerTest.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/xml/ODataXmlDeserializerTest.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/xml/ODataXmlDeserializerTest.java
index dcde3f2..416c219 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/xml/ODataXmlDeserializerTest.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/xml/ODataXmlDeserializerTest.java
@@ -36,6 +36,7 @@ import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
 import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
 import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
 import org.apache.olingo.commons.api.edm.EdmProperty;
+import org.apache.olingo.commons.core.edm.primitivetype.EdmDate;
 import org.apache.olingo.server.api.OData;
 import org.apache.olingo.server.api.deserializer.ODataDeserializer;
 import org.apache.olingo.server.core.deserializer.AbstractODataDeserializerTest;
@@ -47,7 +48,7 @@ import org.junit.Test;
 public class ODataXmlDeserializerTest extends AbstractODataDeserializerTest {
 
   private static final EdmEntityContainer entityContainer = edm.getEntityContainer();
-  private final ODataDeserializer deserializer = new ODataXmlDeserializer();
+  private final ODataDeserializer deserializer = new ODataXmlDeserializer(metadata);
 
   @BeforeClass
   public static void setup() {
@@ -535,6 +536,46 @@ public class ODataXmlDeserializerTest extends AbstractODataDeserializerTest {
   }
 
   @Test
+  public void extendedComplexProperty() throws Exception {
+    final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESCompComp");
+    
+    String payload = "<?xml version='1.0' encoding='UTF-8'?>"
+        + "<atom:entry xmlns:atom=\"http://www.w3.org/2005/Atom\" "
+        + "xmlns:metadata=\"http://docs.oasis-open.org/odata/ns/metadata\" "
+        + "xmlns:data=\"http://docs.oasis-open.org/odata/ns/data\" "
+        + "metadata:etag=\"W/&quot;32767&quot;\">"
+          + "<atom:category scheme=\"http://docs.oasis-open.org/odata/ns/scheme\" "
+          + "term=\"#olingo.odata.test1.ETCompComp\"/>"
+          + "<atom:content type=\"application/xml\">"
+            + "<metadata:properties>"
+              + "<data:PropertyInt16>32767</data:PropertyInt16>"
+              + "<data:PropertyComp metadata:type=\"#olingo.odata.test1.CTCompCompExtended\">"
+                + "<data:PropertyComp metadata:type=\"#olingo.odata.test1.CTTwoPrim\">"
+                  + "<data:PropertyInt16>32767</data:PropertyInt16>"
+                  + "<data:PropertyString>First Resource - first</data:PropertyString>"
+                  + "</data:PropertyComp>"
+                  + "<data:PropertyDate>2012-10-03</data:PropertyDate>"
+              + "</data:PropertyComp>"
+            + "</metadata:properties>"
+          + "</atom:content>"
+        + "</atom:entry>";
+    
+    Entity result = deserializer.entity(new ByteArrayInputStream(payload.getBytes()), 
+        edmEntitySet.getEntityType()).getEntity();
+
+    Assert.assertNotNull(result);
+    Property property = result.getProperty("PropertyComp");
+    Assert.assertEquals("PropertyComp", property.getName());    
+    Assert.assertTrue(property.isComplex());
+    final ComplexValue cv = property.asComplex();
+    Assert.assertEquals("olingo.odata.test1.CTCompCompExtended", property.getType());
+    Assert.assertEquals(
+        "2012-10-03",
+        EdmDate.getInstance().valueToString(getCVProperty(cv, "PropertyDate").asPrimitive(), false, 10, 3, 0,
+        false));
+  }
+  
+  @Test
   public void complexCollectionProperty() throws Exception {
     final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESMixPrimCollComp");
     final EdmProperty edmProperty = (EdmProperty) edmEntitySet.getEntityType().getProperty("CollPropertyComp");