You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by ch...@apache.org on 2016/02/25 15:48:25 UTC

olingo-odata4 git commit: [OLINGO-888] Start with singleton dispatching

Repository: olingo-odata4
Updated Branches:
  refs/heads/OLINGO-888 [created] 7f5c1aa8d


[OLINGO-888] Start with singleton dispatching


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

Branch: refs/heads/OLINGO-888
Commit: 7f5c1aa8de48590ef8954762620067490630631c
Parents: feb94ed
Author: Christian Amend <ch...@sap.com>
Authored: Thu Feb 25 15:47:40 2016 +0100
Committer: Christian Amend <ch...@sap.com>
Committed: Thu Feb 25 15:47:40 2016 +0100

----------------------------------------------------------------------
 .../olingo/server/core/ODataDispatcher.java     | 212 +++++++++++--------
 .../olingo/server/core/ODataHandlerTest.java    |  42 ++++
 2 files changed, 166 insertions(+), 88 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7f5c1aa8/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataDispatcher.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataDispatcher.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataDispatcher.java
index ceacd10..b62282d 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataDispatcher.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataDispatcher.java
@@ -68,6 +68,7 @@ import org.apache.olingo.server.api.uri.UriResourceNavigation;
 import org.apache.olingo.server.api.uri.UriResourcePartTyped;
 import org.apache.olingo.server.api.uri.UriResourcePrimitiveProperty;
 import org.apache.olingo.server.api.uri.UriResourceProperty;
+import org.apache.olingo.server.api.uri.UriResourceSingleton;
 import org.apache.olingo.server.core.batchhandler.BatchHandler;
 import org.apache.olingo.server.core.etag.PreconditionsValidator;
 
@@ -145,6 +146,9 @@ public class ODataDispatcher {
           ((UriResourcePartTyped) lastPathSegment).isCollection(), isEntityOrNavigationMedia(lastPathSegment));
       break;
 
+    case singleton:
+      handleSingleEntityDispatching(request, response, isSingletonMedia(lastPathSegment), true);
+
     case count:
       checkMethod(request.getMethod(), HttpMethod.GET);
       handleCountDispatching(request, response, lastPathSegmentIndex);
@@ -303,60 +307,73 @@ public class ODataDispatcher {
 
   private void handleValueDispatching(final ODataRequest request, final ODataResponse response,
       final int lastPathSegmentIndex) throws ODataApplicationException, ODataLibraryException {
-    //The URI Parser already checked if $value is allowed here so we only have to dispatch to the correct processor
-    final HttpMethod method = request.getMethod();
+    // The URI Parser already checked if $value is allowed here so we only have to dispatch to the correct processor
     final UriResource resource = uriInfo.getUriResourceParts().get(lastPathSegmentIndex - 1);
     if (resource instanceof UriResourceProperty
         || resource instanceof UriResourceFunction
         && ((UriResourceFunction) resource).getType().getKind() == EdmTypeKind.PRIMITIVE) {
-      final EdmType type = resource instanceof UriResourceProperty ?
-          ((UriResourceProperty) resource).getType() : ((UriResourceFunction) resource).getType();
-          final RepresentationType valueRepresentationType =
-              type == EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Binary) ?
-                  RepresentationType.BINARY : RepresentationType.VALUE;
-          if (method == HttpMethod.GET) {
-            final ContentType requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
-                request, handler.getCustomContentTypeSupport(), valueRepresentationType);
-
-            handler.selectProcessor(PrimitiveValueProcessor.class)
-            .readPrimitiveValue(request, response, uriInfo, requestedContentType);
-          } else if (method == HttpMethod.PUT && resource instanceof UriResourceProperty) {
-            validatePreconditions(request, false);
-            final ContentType requestFormat = getSupportedContentType(request.getHeader(HttpHeader.CONTENT_TYPE),
-                valueRepresentationType, true);
-            final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
-                request, handler.getCustomContentTypeSupport(), valueRepresentationType);
-            handler.selectProcessor(PrimitiveValueProcessor.class)
-            .updatePrimitiveValue(request, response, uriInfo, requestFormat, responseFormat);
-          } else if (method == HttpMethod.DELETE && resource instanceof UriResourceProperty) {
-            validatePreconditions(request, false);
-            handler.selectProcessor(PrimitiveValueProcessor.class)
-            .deletePrimitiveValue(request, response, uriInfo);
-          } else {
-            throwMethodNotAllowed(method);
-          }
+      handlePrimitiveValueDispatching(request, response, resource);
     } else {
-      if (method == HttpMethod.GET) {
-        //This can be a GET on an EntitySet, Navigation or Function
-        final ContentType requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
-            request, handler.getCustomContentTypeSupport(), RepresentationType.MEDIA);
-        handler.selectProcessor(MediaEntityProcessor.class)
-        .readMediaEntity(request, response, uriInfo, requestedContentType);
-        //PUT and DELETE can only be called on EntitySets or Navigation properties which are media resources
-      } else if (method == HttpMethod.PUT && isEntityOrNavigationMedia(resource)) {
-        validatePreconditions(request, true);
-        final ContentType requestFormat = ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE));
-        final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
-            request, handler.getCustomContentTypeSupport(), RepresentationType.ENTITY);
-        handler.selectProcessor(MediaEntityProcessor.class)
-        .updateMediaEntity(request, response, uriInfo, requestFormat, responseFormat);
-      } else if (method == HttpMethod.DELETE && isEntityOrNavigationMedia(resource)) {
-        validatePreconditions(request, true);
-        handler.selectProcessor(MediaEntityProcessor.class)
-        .deleteMediaEntity(request, response, uriInfo);
-      } else {
-        throwMethodNotAllowed(method);
-      }
+      handleMediaValueDispatching(request, response, resource);
+    }
+  }
+
+  private void handleMediaValueDispatching(final ODataRequest request, final ODataResponse response,
+      final UriResource resource) throws ContentNegotiatorException, ODataApplicationException, ODataLibraryException,
+      ODataHandlerException, PreconditionException {
+    final HttpMethod method = request.getMethod();
+    if (method == HttpMethod.GET) {
+      // This can be a GET on an EntitySet, Navigation or Function
+      final ContentType requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
+          request, handler.getCustomContentTypeSupport(), RepresentationType.MEDIA);
+      handler.selectProcessor(MediaEntityProcessor.class)
+          .readMediaEntity(request, response, uriInfo, requestedContentType);
+      // PUT and DELETE can only be called on EntitySets or Navigation properties which are media resources
+    } else if (method == HttpMethod.PUT && (isEntityOrNavigationMedia(resource) || isSingletonMedia(resource))) {
+      validatePreconditions(request, true);
+      final ContentType requestFormat = ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE));
+      final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
+          request, handler.getCustomContentTypeSupport(), RepresentationType.ENTITY);
+      handler.selectProcessor(MediaEntityProcessor.class)
+          .updateMediaEntity(request, response, uriInfo, requestFormat, responseFormat);
+    } else if (method == HttpMethod.DELETE && isEntityOrNavigationMedia(resource)) {
+      validatePreconditions(request, true);
+      handler.selectProcessor(MediaEntityProcessor.class)
+          .deleteMediaEntity(request, response, uriInfo);
+    } else {
+      throwMethodNotAllowed(method);
+    }
+  }
+
+  private void handlePrimitiveValueDispatching(final ODataRequest request, final ODataResponse response,
+      final UriResource resource) throws ContentNegotiatorException, ODataApplicationException, ODataLibraryException,
+      ODataHandlerException, PreconditionException {
+    final HttpMethod method = request.getMethod();
+    final EdmType type = resource instanceof UriResourceProperty ?
+        ((UriResourceProperty) resource).getType() : ((UriResourceFunction) resource).getType();
+    final RepresentationType valueRepresentationType =
+        type == EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Binary) ?
+            RepresentationType.BINARY : RepresentationType.VALUE;
+    if (method == HttpMethod.GET) {
+      final ContentType requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
+          request, handler.getCustomContentTypeSupport(), valueRepresentationType);
+
+      handler.selectProcessor(PrimitiveValueProcessor.class)
+          .readPrimitiveValue(request, response, uriInfo, requestedContentType);
+    } else if (method == HttpMethod.PUT && resource instanceof UriResourceProperty) {
+      validatePreconditions(request, false);
+      final ContentType requestFormat = getSupportedContentType(request.getHeader(HttpHeader.CONTENT_TYPE),
+          valueRepresentationType, true);
+      final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
+          request, handler.getCustomContentTypeSupport(), valueRepresentationType);
+      handler.selectProcessor(PrimitiveValueProcessor.class)
+          .updatePrimitiveValue(request, response, uriInfo, requestFormat, responseFormat);
+    } else if (method == HttpMethod.DELETE && resource instanceof UriResourceProperty) {
+      validatePreconditions(request, false);
+      handler.selectProcessor(PrimitiveValueProcessor.class)
+          .deletePrimitiveValue(request, response, uriInfo);
+    } else {
+      throwMethodNotAllowed(method);
     }
   }
 
@@ -466,50 +483,64 @@ public class ODataDispatcher {
 
   private void handleEntityDispatching(final ODataRequest request, final ODataResponse response,
       final boolean isCollection, final boolean isMedia) throws ODataApplicationException, ODataLibraryException {
-    final HttpMethod method = request.getMethod();
     if (isCollection) {
-      if (method == HttpMethod.GET) {
-        final ContentType requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
-            request, handler.getCustomContentTypeSupport(), RepresentationType.COLLECTION_ENTITY);
-        handler.selectProcessor(EntityCollectionProcessor.class)
-            .readEntityCollection(request, response, uriInfo, requestedContentType);
-      } else if (method == HttpMethod.POST) {
-        final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
-            request, handler.getCustomContentTypeSupport(), RepresentationType.ENTITY);
-        if (isMedia) {
-          final ContentType requestFormat = ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE));
-          handler.selectProcessor(MediaEntityProcessor.class)
-              .createMediaEntity(request, response, uriInfo, requestFormat, responseFormat);
-        } else {
-          final ContentType requestFormat = getSupportedContentType(request.getHeader(HttpHeader.CONTENT_TYPE),
-              RepresentationType.ENTITY, true);
-          handler.selectProcessor(EntityProcessor.class)
-              .createEntity(request, response, uriInfo, requestFormat, responseFormat);
-        }
-      } else {
-        throwMethodNotAllowed(method);
-      }
+      handleEntityCollectionDispatching(request, response, isMedia);
     } else {
-      if (method == HttpMethod.GET) {
-        final ContentType requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
-            request, handler.getCustomContentTypeSupport(), RepresentationType.ENTITY);
-        handler.selectProcessor(EntityProcessor.class)
-            .readEntity(request, response, uriInfo, requestedContentType);
-      } else if (method == HttpMethod.PUT || method == HttpMethod.PATCH) {
-        validatePreconditions(request, false);
+      handleSingleEntityDispatching(request, response, isMedia, false);
+    }
+  }
+
+  private void handleEntityCollectionDispatching(final ODataRequest request, final ODataResponse response,
+      final boolean isMedia
+      ) throws ContentNegotiatorException, ODataApplicationException, ODataLibraryException,
+          ODataHandlerException {
+    final HttpMethod method = request.getMethod();
+    if (method == HttpMethod.GET) {
+      final ContentType requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
+          request, handler.getCustomContentTypeSupport(), RepresentationType.COLLECTION_ENTITY);
+      handler.selectProcessor(EntityCollectionProcessor.class)
+          .readEntityCollection(request, response, uriInfo, requestedContentType);
+    } else if (method == HttpMethod.POST) {
+      final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
+          request, handler.getCustomContentTypeSupport(), RepresentationType.ENTITY);
+      if (isMedia) {
+        final ContentType requestFormat = ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE));
+        handler.selectProcessor(MediaEntityProcessor.class)
+            .createMediaEntity(request, response, uriInfo, requestFormat, responseFormat);
+      } else {
         final ContentType requestFormat = getSupportedContentType(request.getHeader(HttpHeader.CONTENT_TYPE),
             RepresentationType.ENTITY, true);
-        final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
-            request, handler.getCustomContentTypeSupport(), RepresentationType.ENTITY);
         handler.selectProcessor(EntityProcessor.class)
-            .updateEntity(request, response, uriInfo, requestFormat, responseFormat);
-      } else if (method == HttpMethod.DELETE) {
-        validatePreconditions(request, false);
-        handler.selectProcessor(isMedia ? MediaEntityProcessor.class : EntityProcessor.class)
-            .deleteEntity(request, response, uriInfo);
-      } else {
-        throwMethodNotAllowed(method);
+            .createEntity(request, response, uriInfo, requestFormat, responseFormat);
       }
+    } else {
+      throwMethodNotAllowed(method);
+    }
+  }
+
+  private void handleSingleEntityDispatching(final ODataRequest request, final ODataResponse response,
+      final boolean isMedia, final boolean isSingleton) throws ContentNegotiatorException, ODataApplicationException,
+      ODataLibraryException, ODataHandlerException, PreconditionException {
+    final HttpMethod method = request.getMethod();
+    if (method == HttpMethod.GET) {
+      final ContentType requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
+          request, handler.getCustomContentTypeSupport(), RepresentationType.ENTITY);
+      handler.selectProcessor(EntityProcessor.class)
+          .readEntity(request, response, uriInfo, requestedContentType);
+    } else if (method == HttpMethod.PUT || method == HttpMethod.PATCH) {
+      validatePreconditions(request, false);
+      final ContentType requestFormat = getSupportedContentType(request.getHeader(HttpHeader.CONTENT_TYPE),
+          RepresentationType.ENTITY, true);
+      final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
+          request, handler.getCustomContentTypeSupport(), RepresentationType.ENTITY);
+      handler.selectProcessor(EntityProcessor.class)
+          .updateEntity(request, response, uriInfo, requestFormat, responseFormat);
+    } else if (method == HttpMethod.DELETE && !isSingleton) {
+      validatePreconditions(request, false);
+      handler.selectProcessor(isMedia ? MediaEntityProcessor.class : EntityProcessor.class)
+          .deleteEntity(request, response, uriInfo);
+    } else {
+      throwMethodNotAllowed(method);
     }
   }
 
@@ -558,8 +589,13 @@ public class ODataDispatcher {
     return contentType;
   }
 
+  private boolean isSingletonMedia(final UriResource pathSegment) {
+    return pathSegment instanceof UriResourceSingleton
+        && ((UriResourceSingleton) pathSegment).getEntityType().hasStream();
+  }
+
   private boolean isEntityOrNavigationMedia(final UriResource pathSegment) {
-    //This method MUST NOT check if the resource is of type function since these are handled differently
+    // This method MUST NOT check if the resource is of type function since these are handled differently
     return pathSegment instanceof UriResourceEntitySet
         && ((UriResourceEntitySet) pathSegment).getEntityType().hasStream()
         || pathSegment instanceof UriResourceNavigation

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7f5c1aa8/lib/server-test/src/test/java/org/apache/olingo/server/core/ODataHandlerTest.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/ODataHandlerTest.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/ODataHandlerTest.java
index a228e40..b973cba 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/ODataHandlerTest.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/ODataHandlerTest.java
@@ -471,6 +471,48 @@ public class ODataHandlerTest {
 
     dispatchMethodNotAllowed(HttpMethod.POST, uri, processor);
   }
+  
+  @Test
+  public void dispatchSingleton() throws Exception {
+    final String uri = "SI";
+    final EntityProcessor processor = mock(EntityProcessor.class);
+    
+    dispatch(HttpMethod.GET, uri, processor);
+    verify(processor).readEntity(
+        any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class));
+
+    dispatch(HttpMethod.PATCH, uri, processor);
+    verify(processor).updateEntity(
+        any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class),
+        any(ContentType.class));
+
+    dispatch(HttpMethod.PUT, uri, processor);
+    verify(processor, times(2)).updateEntity(
+        any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class),
+        any(ContentType.class));
+
+    dispatchMethodNotAllowed(HttpMethod.POST, uri, processor);
+    dispatchMethodNotAllowed(HttpMethod.DELETE, uri, processor);
+  }
+  
+  @Test
+  public void dispatchSingletonMedia() throws Exception {
+    final String uri = "SIMedia/$value";
+    final MediaEntityProcessor processor = mock(MediaEntityProcessor.class);
+    
+    dispatch(HttpMethod.GET, uri, processor);
+    verify(processor).readMediaEntity(
+        any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class));
+
+    dispatch(HttpMethod.PUT, uri, processor);
+    verify(processor).updateMediaEntity(
+        any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class),
+        any(ContentType.class));
+
+    dispatchMethodNotAllowed(HttpMethod.PATCH, uri, processor);
+    dispatchMethodNotAllowed(HttpMethod.POST, uri, processor);
+    dispatchMethodNotAllowed(HttpMethod.DELETE, uri, processor);
+  }
 
   @Test
   public void dispatchMedia() throws Exception {