/*
 * 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.io.IOException;
import java.util.List;

import org.apache.olingo.commons.api.edm.EdmAction;
import org.apache.olingo.commons.api.edm.EdmEntityType;
import org.apache.olingo.commons.api.edm.EdmFunction;
import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
import org.apache.olingo.commons.api.edm.EdmReturnType;
import org.apache.olingo.commons.api.edm.EdmSingleton;
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.HttpMethod;
import org.apache.olingo.commons.core.edm.primitivetype.EdmPrimitiveTypeFactory;
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.etag.CustomETagSupport;
import org.apache.olingo.server.api.etag.PreconditionException;
import org.apache.olingo.server.api.processor.ActionComplexCollectionProcessor;
import org.apache.olingo.server.api.processor.ActionComplexProcessor;
import org.apache.olingo.server.api.processor.ActionEntityCollectionProcessor;
import org.apache.olingo.server.api.processor.ActionEntityProcessor;
import org.apache.olingo.server.api.processor.ActionPrimitiveCollectionProcessor;
import org.apache.olingo.server.api.processor.ActionPrimitiveProcessor;
import org.apache.olingo.server.api.processor.ActionVoidProcessor;
import org.apache.olingo.server.api.processor.BatchProcessor;
import org.apache.olingo.server.api.processor.ComplexCollectionProcessor;
import org.apache.olingo.server.api.processor.ComplexProcessor;
import org.apache.olingo.server.api.processor.CountComplexCollectionProcessor;
import org.apache.olingo.server.api.processor.CountEntityCollectionProcessor;
import org.apache.olingo.server.api.processor.CountPrimitiveCollectionProcessor;
import org.apache.olingo.server.api.processor.EntityCollectionProcessor;
import org.apache.olingo.server.api.processor.EntityProcessor;
import org.apache.olingo.server.api.processor.MediaEntityProcessor;
import org.apache.olingo.server.api.processor.MetadataProcessor;
import org.apache.olingo.server.api.processor.PrimitiveCollectionProcessor;
import org.apache.olingo.server.api.processor.PrimitiveProcessor;
import org.apache.olingo.server.api.processor.PrimitiveValueProcessor;
import org.apache.olingo.server.api.processor.ReferenceCollectionProcessor;
import org.apache.olingo.server.api.processor.ReferenceProcessor;
import org.apache.olingo.server.api.processor.ServiceDocumentProcessor;
import org.apache.olingo.server.api.serializer.RepresentationType;
import org.apache.olingo.server.api.uri.UriInfo;
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.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;

public class ODataDispatcher {

  private static final String NOT_IMPLEMENTED_MESSAGE = "not implemented";
  private final UriInfo uriInfo;
  private final ODataHandlerImpl handler;
  private static final String RETURN_MINIMAL = "return=minimal";
  private static final String RETURN_REPRESENTATION = "return=representation";
  private static final String EDMSTREAM = "Edm.Stream";

  public ODataDispatcher(final UriInfo uriInfo, final ODataHandlerImpl handler) {
    this.uriInfo = uriInfo;
    this.handler = handler;
  }

  public void dispatch(final ODataRequest request, final ODataResponse response) throws ODataApplicationException,
      ODataLibraryException {
    switch (uriInfo.getKind()) {
    case metadata:
      checkMethods(request.getMethod(), HttpMethod.GET, HttpMethod.HEAD);
      final ContentType requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
          request, handler.getCustomContentTypeSupport(), RepresentationType.METADATA);
      handler.selectProcessor(MetadataProcessor.class)
          .readMetadata(request, response, uriInfo, requestedContentType);
      break;

    case service:
      checkMethods(request.getMethod(), HttpMethod.GET, HttpMethod.HEAD);
      if ("".equals(request.getRawODataPath())) {
        handler.selectProcessor(RedirectProcessor.class)
            .redirect(request, response);
      } else {
        final ContentType serviceContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
            request, handler.getCustomContentTypeSupport(), RepresentationType.SERVICE);
        handler.selectProcessor(ServiceDocumentProcessor.class)
            .readServiceDocument(request, response, uriInfo, serviceContentType);
      }
      break;

    case resource:
    case entityId:
      handleResourceDispatching(request, response);
      break;

    case batch:
      checkMethod(request.getMethod(), HttpMethod.POST);
      new BatchHandler(handler, handler.selectProcessor(BatchProcessor.class))
          .process(request, response, true);
      break;

    default:
      throw new ODataHandlerException(NOT_IMPLEMENTED_MESSAGE,
          ODataHandlerException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED);
    }
  }

  private void handleResourceDispatching(final ODataRequest request, final ODataResponse response)
      throws ODataApplicationException, ODataLibraryException {

    final int lastPathSegmentIndex = uriInfo.getUriResourceParts().size() - 1;
    final UriResource lastPathSegment = uriInfo.getUriResourceParts().get(lastPathSegmentIndex);

    switch (lastPathSegment.getKind()) {
    case action:
      checkMethod(request.getMethod(), HttpMethod.POST);
      handleActionDispatching(request, response, (UriResourceAction) lastPathSegment);
      break;

    case function:
      checkMethod(request.getMethod(), HttpMethod.GET);
      handleFunctionDispatching(request, response, (UriResourceFunction) lastPathSegment);
      break;

    case entitySet:
    case navigationProperty:
      handleEntityDispatching(request, response,
          ((UriResourcePartTyped) lastPathSegment).isCollection(), isEntityOrNavigationMedia(lastPathSegment));
      break;
      
    case singleton:
      handleSingleEntityDispatching(request, response, isSingletonMedia(lastPathSegment), true);
      break;
      
    case count:
      checkMethod(request.getMethod(), HttpMethod.GET);
      handleCountDispatching(request, response, lastPathSegmentIndex);
      break;

    case primitiveProperty:
      handlePrimitiveDispatching(request, response,
          ((UriResourceProperty) lastPathSegment).isCollection());
      break;

    case complexProperty:
      handleComplexDispatching(request, response,
          ((UriResourceProperty) lastPathSegment).isCollection());
      break;

    case value:
      handleValueDispatching(request, response, lastPathSegmentIndex);
      break;

    case ref:
      handleReferenceDispatching(request, response, lastPathSegmentIndex);
      break;

    default:
      throw new ODataHandlerException(NOT_IMPLEMENTED_MESSAGE,
          ODataHandlerException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED);
    }
  }

  private void handleFunctionDispatching(final ODataRequest request, final ODataResponse response,
      final UriResourceFunction uriResourceFunction) throws ODataApplicationException, ODataLibraryException {
    EdmFunction function = uriResourceFunction.getFunction();
    if (function == null) {
      function = uriResourceFunction.getFunctionImport().getUnboundFunctions().get(0);
    }
    final EdmReturnType returnType = function.getReturnType();
    switch (returnType.getType().getKind()) {
    case ENTITY:
      handleEntityDispatching(request, response,
          returnType.isCollection() && uriResourceFunction.getKeyPredicates().isEmpty(),
          false);
      break;
    case PRIMITIVE:
      handlePrimitiveDispatching(request, response, returnType.isCollection());
      break;
    case COMPLEX:
      handleComplexDispatching(request, response, returnType.isCollection());
      break;
    default:
      throw new ODataHandlerException(NOT_IMPLEMENTED_MESSAGE,
          ODataHandlerException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED);
    }
  }

  private void handleActionDispatching(final ODataRequest request, final ODataResponse response,
      final UriResourceAction uriResourceAction) throws ODataApplicationException, ODataLibraryException {
    final EdmAction action = uriResourceAction.getAction();
    if (action.isBound()) {
      // Only bound actions can have ETag control for the binding parameter.
      validatePreconditions(request, false);
    }
    final ContentType requestFormat = getSupportedContentType(request.getHeader(HttpHeader.CONTENT_TYPE),
        RepresentationType.ACTION_PARAMETERS, false);
    final EdmReturnType returnType = action.getReturnType();
    if (returnType == null) {
      handler.selectProcessor(ActionVoidProcessor.class)
          .processActionVoid(request, response, uriInfo, requestFormat);
    } else {
      final boolean isCollection = returnType.isCollection();
      ContentType responseFormat;
      switch (returnType.getType().getKind()) {
      case ENTITY:
        responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
            request, handler.getCustomContentTypeSupport(),
            isCollection ? RepresentationType.COLLECTION_ENTITY : RepresentationType.ENTITY);
        if (isCollection) {
          handler.selectProcessor(ActionEntityCollectionProcessor.class)
              .processActionEntityCollection(request, response, uriInfo, requestFormat, responseFormat);
        } else {
          handler.selectProcessor(ActionEntityProcessor.class)
              .processActionEntity(request, response, uriInfo, requestFormat, responseFormat);
        }
        break;

      case PRIMITIVE:
        responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
            request, handler.getCustomContentTypeSupport(),
            isCollection ? RepresentationType.COLLECTION_PRIMITIVE : RepresentationType.PRIMITIVE);
        if (isCollection) {
          handler.selectProcessor(ActionPrimitiveCollectionProcessor.class)
              .processActionPrimitiveCollection(request, response, uriInfo, requestFormat, responseFormat);
        } else {
          handler.selectProcessor(ActionPrimitiveProcessor.class)
              .processActionPrimitive(request, response, uriInfo, requestFormat, responseFormat);
        }
        break;

      case COMPLEX:
        responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
            request, handler.getCustomContentTypeSupport(),
            isCollection ? RepresentationType.COLLECTION_COMPLEX : RepresentationType.COMPLEX);
        if (isCollection) {
          handler.selectProcessor(ActionComplexCollectionProcessor.class)
              .processActionComplexCollection(request, response, uriInfo, requestFormat, responseFormat);
        } else {
          handler.selectProcessor(ActionComplexProcessor.class)
              .processActionComplex(request, response, uriInfo, requestFormat, responseFormat);
        }
        break;

      default:
        throw new ODataHandlerException(NOT_IMPLEMENTED_MESSAGE,
            ODataHandlerException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED);
      }
    }
  }

  private void handleReferenceDispatching(final ODataRequest request, final ODataResponse response,
      final int lastPathSegmentIndex) throws ODataApplicationException, ODataLibraryException {
    final HttpMethod httpMethod = request.getMethod();
    final boolean isCollection = ((UriResourcePartTyped) uriInfo.getUriResourceParts()
        .get(lastPathSegmentIndex - 1))
            .isCollection();

    if (isCollection && httpMethod == HttpMethod.GET) {
      validatePreferHeader(request);
      final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
          request, handler.getCustomContentTypeSupport(), RepresentationType.COLLECTION_REFERENCE);
      handler.selectProcessor(ReferenceCollectionProcessor.class)
          .readReferenceCollection(request, response, uriInfo, responseFormat);

    } else if (isCollection && httpMethod == HttpMethod.POST) {
      final ContentType requestFormat = getSupportedContentType(request.getHeader(HttpHeader.CONTENT_TYPE),
          RepresentationType.REFERENCE, true);
      handler.selectProcessor(ReferenceProcessor.class)
          .createReference(request, response, uriInfo, requestFormat);

    } else if (!isCollection && httpMethod == HttpMethod.GET) {
      validatePreferHeader(request);
      final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
          request, handler.getCustomContentTypeSupport(), RepresentationType.REFERENCE);
      handler.selectProcessor(ReferenceProcessor.class).readReference(request, response, uriInfo, responseFormat);

    } else if (!isCollection && (httpMethod == HttpMethod.PUT || httpMethod == HttpMethod.PATCH)) {
      final ContentType requestFormat = getSupportedContentType(request.getHeader(HttpHeader.CONTENT_TYPE),
          RepresentationType.REFERENCE, true);
      handler.selectProcessor(ReferenceProcessor.class)
          .updateReference(request, response, uriInfo, requestFormat);

    } else if (httpMethod == HttpMethod.DELETE) {
      validatePreferHeader(request);
      handler.selectProcessor(ReferenceProcessor.class)
          .deleteReference(request, response, uriInfo);

    } else {
      throwMethodNotAllowed(httpMethod);
    }
  }

  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 UriResource resource = uriInfo.getUriResourceParts().get(lastPathSegmentIndex - 1);
    if (resource instanceof UriResourceProperty
        || resource instanceof UriResourceFunction
            && ((UriResourceFunction) resource).getType().getKind() == EdmTypeKind.PRIMITIVE) {
      handlePrimitiveValueDispatching(request, response, resource);
    } else {
      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();
    validatePreferHeader(request);
    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) {
      validatePreferHeader(request);
      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) {
      validatePreferHeader(request);
      validatePreconditions(request, false);
      handler.selectProcessor(PrimitiveValueProcessor.class)
          .deletePrimitiveValue(request, response, uriInfo);
    } else {
      throwMethodNotAllowed(method);
    }
  }
  
  private void handleComplexDispatching(final ODataRequest request, final ODataResponse response,
      final boolean isCollection) throws ODataApplicationException, ODataLibraryException {
    final HttpMethod method = request.getMethod();
    final RepresentationType complexRepresentationType = isCollection ? RepresentationType.COLLECTION_COMPLEX
        : RepresentationType.COMPLEX;
    if (method == HttpMethod.GET) {
      validatePreferHeader(request);
      final ContentType requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
          request, handler.getCustomContentTypeSupport(), complexRepresentationType);
      if (isCollection) {
        handler.selectProcessor(ComplexCollectionProcessor.class)
            .readComplexCollection(request, response, uriInfo, requestedContentType);
      } else {
        handler.selectProcessor(ComplexProcessor.class)
            .readComplex(request, response, uriInfo, requestedContentType);
      }
    } else if (method == HttpMethod.PUT || method == HttpMethod.PATCH) {
      validatePreconditions(request, false);
      final ContentType requestFormat = getSupportedContentType(request.getHeader(HttpHeader.CONTENT_TYPE),
          complexRepresentationType, true);
      final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
          request, handler.getCustomContentTypeSupport(), complexRepresentationType);
      if (isCollection) {
        handler.selectProcessor(ComplexCollectionProcessor.class)
            .updateComplexCollection(request, response, uriInfo, requestFormat, responseFormat);
      } else {
        handler.selectProcessor(ComplexProcessor.class)
            .updateComplex(request, response, uriInfo, requestFormat, responseFormat);
      }
    } else if (method == HttpMethod.DELETE) {
      validatePreferHeader(request);
      validatePreconditions(request, false);
      if (isCollection) {
        handler.selectProcessor(ComplexCollectionProcessor.class)
            .deleteComplexCollection(request, response, uriInfo);
      } else {
        handler.selectProcessor(ComplexProcessor.class)
            .deleteComplex(request, response, uriInfo);
      }
    } else {
      throwMethodNotAllowed(method);
    }
  }

  private void handlePrimitiveDispatching(final ODataRequest request, final ODataResponse response,
      final boolean isCollection) throws ODataApplicationException, ODataLibraryException {
    final HttpMethod method = request.getMethod();
    final RepresentationType representationType = isCollection ? RepresentationType.COLLECTION_PRIMITIVE
        : RepresentationType.PRIMITIVE;
    if (method == HttpMethod.GET) {
      validatePreferHeader(request);
      final ContentType requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
          request, handler.getCustomContentTypeSupport(), representationType);
      if (isCollection) {
        handler.selectProcessor(PrimitiveCollectionProcessor.class)
            .readPrimitiveCollection(request, response, uriInfo, requestedContentType);
      } else {
        handler.selectProcessor(PrimitiveProcessor.class)
            .readPrimitive(request, response, uriInfo, requestedContentType);
      }
    } else if (method == HttpMethod.PUT || method == HttpMethod.PATCH) {
      validatePreconditions(request, false);
      ContentType requestFormat = null;
      List<UriResource> uriResources = uriInfo.getUriResourceParts();
      UriResource uriResource = uriResources.get(uriResources.size() - 1);
      if (uriResource instanceof UriResourcePrimitiveProperty &&
    		  ((UriResourcePrimitiveProperty)uriResource).getType()
    		  .getFullQualifiedName().getFullQualifiedNameAsString().equalsIgnoreCase(EDMSTREAM)) {
    	 requestFormat = ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE));
      } else {
    	  requestFormat = getSupportedContentType(request.getHeader(HttpHeader.CONTENT_TYPE),
    	          representationType, true);
      }
      final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
          request, handler.getCustomContentTypeSupport(), representationType);
      if (isCollection) {
        handler.selectProcessor(PrimitiveCollectionProcessor.class)
            .updatePrimitiveCollection(request, response, uriInfo, requestFormat, responseFormat);
      } else {
        handler.selectProcessor(PrimitiveProcessor.class)
            .updatePrimitive(request, response, uriInfo, requestFormat, responseFormat);
      }
    } else if (method == HttpMethod.DELETE) {
      validatePreferHeader(request);
      validatePreconditions(request, false);
      if (isCollection) {
        handler.selectProcessor(PrimitiveCollectionProcessor.class)
            .deletePrimitiveCollection(request, response, uriInfo);
      } else {
        handler.selectProcessor(PrimitiveProcessor.class)
            .deletePrimitive(request, response, uriInfo);
      }
    } else {
      throwMethodNotAllowed(method);
    }
  }

  private void handleCountDispatching(final ODataRequest request, final ODataResponse response,
      final int lastPathSegmentIndex) throws ODataApplicationException, ODataLibraryException {
    validatePreferHeader(request);
    final UriResource resource = uriInfo.getUriResourceParts().get(lastPathSegmentIndex - 1);
    if (resource instanceof UriResourceEntitySet
        || resource instanceof UriResourceNavigation
        || resource instanceof UriResourceFunction
            && ((UriResourceFunction) resource).getType().getKind() == EdmTypeKind.ENTITY) {
      handler.selectProcessor(CountEntityCollectionProcessor.class)
          .countEntityCollection(request, response, uriInfo);
    } else if (resource instanceof UriResourcePrimitiveProperty
        || resource instanceof UriResourceFunction
            && ((UriResourceFunction) resource).getType().getKind() == EdmTypeKind.PRIMITIVE) {
      handler.selectProcessor(CountPrimitiveCollectionProcessor.class)
          .countPrimitiveCollection(request, response, uriInfo);
    } else {
      handler.selectProcessor(CountComplexCollectionProcessor.class)
          .countComplexCollection(request, response, uriInfo);
    }
  }

  private void handleEntityDispatching(final ODataRequest request, final ODataResponse response,
      final boolean isCollection, final boolean isMedia) throws ODataApplicationException, ODataLibraryException {
    if (isCollection) {
      handleEntityCollectionDispatching(request, response, isMedia);
      } else {
        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) {
      validatePreferHeader(request);
      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) {
        validatePreferHeader(request);
        final ContentType requestFormat = ContentType.parse(
            request.getHeader(HttpHeader.CONTENT_TYPE));
        handler.selectProcessor(MediaEntityProcessor.class)
            .createMediaEntity(request, response, uriInfo, requestFormat, responseFormat);
      } else {
        try {
         final ContentType requestFormat = (request.getHeader(HttpHeader.CONTENT_TYPE) == null && 
             (request.getBody() == null || request.getBody().available() == 0)) ?
            getSupportedContentType(
            request.getHeader(HttpHeader.CONTENT_TYPE),
            RepresentationType.ENTITY, false) : getSupportedContentType(
                request.getHeader(HttpHeader.CONTENT_TYPE),
                RepresentationType.ENTITY, true);
            handler.selectProcessor(EntityProcessor.class)
            .createEntity(request, response, uriInfo, requestFormat, responseFormat);
        } catch (IOException e) {
          throw new ODataHandlerException("There is problem in the payload.",
              ODataHandlerException.MessageKeys.INVALID_PAYLOAD);
        }
      }
    } else {
      throwMethodNotAllowed(method);
    }
  }

  /**Checks if Prefer header is set with return=minimal or 
   * return=representation for GET and DELETE requests
   * @param request
   * @throws ODataHandlerException
   */
  private void validatePreferHeader(final ODataRequest request) throws ODataHandlerException {
    final List<String> returnPreference = request.getHeaders(HttpHeader.PREFER);
    if (null != returnPreference) {
      for (String preference : returnPreference) {
        if (preference.equals(RETURN_MINIMAL) || preference.equals(RETURN_REPRESENTATION)) {
          throw new ODataHandlerException("Prefer Header not supported: " + preference,
              ODataHandlerException.MessageKeys.INVALID_PREFER_HEADER, preference);
        } 
      }
    }
  }
  
  private boolean isSingletonMedia(final UriResource pathSegment) { 
   return pathSegment instanceof UriResourceSingleton
       && ((UriResourceSingleton) pathSegment).getEntityType().hasStream();
  }

  
   
  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) {
        validatePreferHeader(request);
        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) {
        if (isMedia) {
          validatePreferHeader(request);
        }
        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) {
        validateIsSingleton(method);
        validatePreconditions(request, false);
        validatePreferHeader(request);
        if (isMedia) {
          ((MediaEntityProcessor) handler.selectProcessor(MediaEntityProcessor.class))
          .deleteEntity(request, response, uriInfo);
          } else {
          ((EntityProcessor) handler.selectProcessor(EntityProcessor.class))
          .deleteEntity(request, response, uriInfo);
        }
      } else {
        throwMethodNotAllowed(method);
      }
    }

  /*Delete method is not allowed for Entities navigating to Singleton*/ 
  private void validateIsSingleton(HttpMethod method) throws ODataHandlerException {
    final int lastPathSegmentIndex = uriInfo.getUriResourceParts().size() - 1;
    final UriResource pathSegment = uriInfo.getUriResourceParts().get(lastPathSegmentIndex);
    if (pathSegment instanceof UriResourceNavigation
        && uriInfo.getUriResourceParts().get(lastPathSegmentIndex - 1) instanceof UriResourceEntitySet
        && ((UriResourceEntitySet) uriInfo.getUriResourceParts().get(lastPathSegmentIndex - 1)).getEntitySet()
            .getRelatedBindingTarget(
                pathSegment.getSegmentValue()) instanceof EdmSingleton) {
      throwMethodNotAllowed(method);
    }
  }


  private void validatePreconditions(final ODataRequest request, final boolean isMediaValue)
      throws PreconditionException {
    // If needed perform preconditions validation.
    final CustomETagSupport eTagSupport = handler.getCustomETagSupport();
    if (eTagSupport != null
        && new PreconditionsValidator(uriInfo).mustValidatePreconditions(eTagSupport, isMediaValue)
        && request.getHeader(HttpHeader.IF_MATCH) == null
        && request.getHeader(HttpHeader.IF_NONE_MATCH) == null) {
      throw new PreconditionException("Expected an if-match or if-none-match header.",
          PreconditionException.MessageKeys.MISSING_HEADER);
    }
  }

  private void checkMethod(final HttpMethod requestMethod, final HttpMethod allowedMethod)
      throws ODataHandlerException {
    if (requestMethod != allowedMethod) {
      throwMethodNotAllowed(requestMethod);
    }
  }

  private void checkMethods(final HttpMethod requestMethod, final HttpMethod... allowedMethods)
      throws ODataHandlerException {
    //Check if the request method is one of the allowed ones
    for (int i = 0; i < allowedMethods.length; i++) {
      if (requestMethod == allowedMethods[i]) {
        return;
      }
    }
    //request method does not match any allowed method
    throwMethodNotAllowed(requestMethod);
  }

  private void throwMethodNotAllowed(final HttpMethod httpMethod) throws ODataHandlerException {
    throw new ODataHandlerException("HTTP method " + httpMethod + " is not allowed.",
        ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED, httpMethod.toString());
  }

  private ContentType getSupportedContentType(final String contentTypeHeader,
      final RepresentationType representationType, final boolean mustNotBeNull)
      throws ODataHandlerException, ContentNegotiatorException {
    if (contentTypeHeader == null) {
      if (mustNotBeNull) {
        throw new ODataHandlerException("ContentTypeHeader parameter is null",
            ODataHandlerException.MessageKeys.MISSING_CONTENT_TYPE);
      }
      return ContentType.APPLICATION_JSON;
    }
    ContentType contentType;
    try {
      contentType = ContentType.create(contentTypeHeader);
    } catch (final IllegalArgumentException e) {
      throw new ODataHandlerException("Illegal content type.", e,
          ODataHandlerException.MessageKeys.INVALID_CONTENT_TYPE, contentTypeHeader);
    }
    ContentNegotiator.checkSupport(contentType, handler.getCustomContentTypeSupport(), representationType);
    return contentType;
  }

  private boolean isEntityOrNavigationMedia(final UriResource pathSegment) {
    // 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
            && ((EdmEntityType) ((UriResourceNavigation) pathSegment).getType()).hasStream();
  }

}
