/*
 * 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.uri.validator;

import java.util.HashMap;
import java.util.List;

import org.apache.olingo.commons.api.edm.EdmAction;
import org.apache.olingo.commons.api.edm.EdmActionImport;
import org.apache.olingo.commons.api.edm.EdmEntityType;
import org.apache.olingo.commons.api.edm.EdmFunction;
import org.apache.olingo.commons.api.edm.EdmFunctionImport;
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.EdmSingleton;
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.UriResourceSingleton;
import org.apache.olingo.server.api.uri.queryoption.SystemQueryOption;
import org.apache.olingo.server.api.uri.queryoption.SystemQueryOptionKind;

public class UriValidator {

  //@formatter:off (Eclipse formatter)
  //CHECKSTYLE:OFF (Maven checkstyle)
  private boolean[][] decisionMatrix =
      {
          /*                                          0-FILTER 1-FORMAT 2-EXPAND 3-ID     4-COUNT  5-ORDERBY 6-SEARCH 7-SELECT 8-SKIP   9-SKIPTOKEN 10-LEVELS 11-TOP */
          /*                              all  0 */ { true ,   true ,   true ,   false,   true ,   true ,    true ,   true ,   true ,   true ,      true ,    false },
          /*                            batch  1 */ { false,   false,   false,   false,   false,   false,    false,   false,   false,   false,      false,    false },
          /*                        crossjoin  2 */ { true ,   true ,   true ,   false,   true ,   true ,    true ,   true ,   true ,   true ,      true ,    true  },
          /*                         entityId  3 */ { false,   true ,   true ,   true ,   false,   false,    false,   true ,   false,   false,      true ,    false },
          /*                         metadata  4 */ { false,   true ,   false,   false,   false,   false,    false,   false,   false,   false,      false,    false },
          /*                         resource  5 */ { false,   true ,   false,   false,   false,   false,    false,   false,   false,   false,      false,    false },
          /*                          service  6 */ { false,   true ,   false,   false,   false,   false,    false,   false,   false,   false,      false,    false },
          /*                        entitySet  7 */ { true ,   true ,   true ,   false,   true ,   true ,    true ,   true ,   true ,   true ,      true ,    true  },
          /*                   entitySetCount  8 */ { true,    false,   false,   false,   false,   false,    true,    false,   false,   false,      false,    false },
          /*                           entity  9 */ { false,   true ,   true ,   false,   false,   false,    false,   true ,   false,   false,      true ,    false },
          /*                      mediaStream 10 */ { false,   true ,   false,   false,   false,   false,    false,   false,   false,   false,      false,    false },
          /*                       references 11 */ { true ,   true ,   false,   false,   false,   true ,    true ,   false,   true ,   true ,      false,    true  },
          /*                        reference 12 */ { false,   true ,   false,   false,   false,   false,    false,   false,   false,   false,      false,    false },
          /*                  propertyComplex 13 */ { false,   true ,   true ,   false,   false,   false,    false,   true ,   false,   false,      true ,    false },
          /*        propertyComplexCollection 14 */ { true ,   true ,   true ,   false,   true ,   true ,    false,   false,   true ,   true ,      true ,    true  },
          /*   propertyComplexCollectionCount 15 */ { true,    false,   false,   false,   false,   false,    true,    false,   false,   false,      false,    false },
          /*                propertyPrimitive 16 */ { false,   true ,   false,   false,   false,   false,    false,   false,   false,   false,      false,    false },
          /*      propertyPrimitiveCollection 17 */ { true ,   true ,   false,   false,   false,   true ,    false,   false,   true ,   true ,      false,    true  },
          /* propertyPrimitiveCollectionCount 18 */ { true,    false,   false,   false,   false,   false,    true,    false,   false,   false,      false,    false },
          /*           propertyPrimitiveValue 19 */ { false,   true ,   false,   false,   false,   false,    false,   false,   false,   false,      false,    false },                    
      };

  private boolean[][] decisionMatrixForHttpMethod =
    {
        /*                                          0-FILTER 1-FORMAT 2-EXPAND 3-ID     4-COUNT  5-ORDERBY 6-SEARCH 7-SELECT 8-SKIP   9-SKIPTOKEN 10-LEVELS 11-TOP */
        /*                              GET  0 */ { true ,   true ,   true ,   true,    true ,   true ,    true ,   true ,   true ,   true ,      true ,    true },
        /*                             POST  0 */ { true ,   false ,  true ,   false,   false ,  true ,    false ,  true ,   false ,  false ,     true ,    false },
        /*                              PUT  0 */ { false ,  false ,  false ,  false,   false ,  false ,   false ,  false ,  false ,  false ,     false ,   false },
        /*                           DELETE  0 */ { false ,  false ,  false ,  false,   false ,  false,    false ,  false,   false ,  false ,     false,    false },
        /*                            PATCH  0 */ { false ,  false ,  false ,  false,   false ,  false ,   false ,  false ,  false ,  false ,     false ,   false },
    };

  //CHECKSTYLE:ON
  //@formatter:on

  private enum RowIndexForUriType {
    all(0),
    batch(1),
    crossjoin(2),
    entityId(3),
    metadata(4),
    resource(5),
    service(6),
    entitySet(7),
    entitySetCount(8),
    entity(9),
    mediaStream(10),
    references(11),
    reference(12),
    propertyComplex(13),
    propertyComplexCollection(14),
    propertyComplexCollectionCount(15),
    propertyPrimitive(16),
    propertyPrimitiveCollection(17),
    propertyPrimitiveCollectionCount(18),
    propertyPrimitiveValue(19);

    private int idx;

    RowIndexForUriType(final int i) {
      idx = i;
    }

    public int getIndex() {
      return idx;
    }
  }

  private enum ColumnIndex {
    filter(0),
    format(1),
    expand(2),
    id(3),
    count(4),
    orderby(5),
    search(6),
    select(7),
    skip(8),
    skiptoken(9),
    levels(10),
    top(11);

    private int idx;

    ColumnIndex(final int i) {
      idx = i;
    }

    public int getIndex() {
      return idx;
    }

  }

  private enum RowIndexForHttpMethod {
    GET(0),
    POST(1),
    PUT(2),
    DELETE(3),
    PATCH(4);

    private int idx;

    RowIndexForHttpMethod(final int i) {
      idx = i;
    }

    public int getIndex() {
      return idx;
    }

  }

  public UriValidator() {
    super();
  }

  public void validate(final UriInfo uriInfo, final HttpMethod httpMethod) throws UriValidationException {
    validateForHttpMethod(uriInfo, httpMethod);
    validateQueryOptions(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 LEVELS:
      idx = ColumnIndex.levels;
      break;
    case TOP:
      idx = ColumnIndex.top;
      break;
    default:
      throw new UriValidationException("Unsupported option: " + queryOptionKind.toString(),
          UriValidationException.MessageKeys.UNSUPPORTED_QUERY_OPTION, queryOptionKind.toString());
    }

    return idx;
  }

  private RowIndexForUriType rowIndexForUriType(final UriInfo uriInfo) throws UriValidationException {
    RowIndexForUriType idx;

    switch (uriInfo.getKind()) {
    case all:
      idx = RowIndexForUriType.all;
      break;
    case batch:
      idx = RowIndexForUriType.batch;
      break;
    case crossjoin:
      idx = RowIndexForUriType.crossjoin;
      break;
    case entityId:
      idx = RowIndexForUriType.entityId;
      break;
    case metadata:
      idx = RowIndexForUriType.metadata;
      break;
    case resource:
      idx = rowIndexForResourceKind(uriInfo);
      break;
    case service:
      idx = RowIndexForUriType.service;
      break;
    default:
      throw new UriValidationException("Unsupported uriInfo kind: " + uriInfo.getKind(),
          UriValidationException.MessageKeys.UNSUPPORTED_URI_KIND, uriInfo.getKind().toString());
    }

    return idx;
  }

  private RowIndexForUriType rowIndexForResourceKind(final UriInfo uriInfo) throws UriValidationException {
    RowIndexForUriType idx;

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

    switch (lastPathSegment.getKind()) {
    case count:
      idx = rowIndexForCount(uriInfo);
      break;
    case action:
      idx = rowIndexForAction(lastPathSegment);
      break;
    case complexProperty:
      idx = rowIndexForComplexProperty(lastPathSegment);
      break;
    case entitySet:
      idx = rowIndexForEntitySet(lastPathSegment);
      break;
    case function:
      idx = rowIndexForFunction(lastPathSegment);
      break;
    case navigationProperty:
      idx =
          ((UriResourceNavigation) lastPathSegment).isCollection() ? RowIndexForUriType.entitySet
              : RowIndexForUriType.entity;
      break;
    case primitiveProperty:
      idx = rowIndexForPrimitiveProperty(lastPathSegment);
      break;
    case ref:
      idx = rowIndexForRef(uriInfo, lastPathSegment);
      break;
    case root:
      idx = RowIndexForUriType.service;
      break;
    case singleton:
      idx = RowIndexForUriType.entity;
      break;
    case value:
      idx = rowIndexForValue(uriInfo);
      break;
    default:
      throw new UriValidationException("Unsupported uriResource kind: " + lastPathSegment.getKind(),
          UriValidationException.MessageKeys.UNSUPPORTED_URI_RESOURCE_KIND, lastPathSegment.getKind().toString());
    }

    return idx;
  }

  private RowIndexForUriType rowIndexForValue(final UriInfo uriInfo) throws UriValidationException {
    RowIndexForUriType idx;
    int secondLastPathSegmentIndex = uriInfo.getUriResourceParts().size() - 2;
    UriResource secondLastPathSegment = uriInfo.getUriResourceParts().get(secondLastPathSegmentIndex);

    switch (secondLastPathSegment.getKind()) {
    case primitiveProperty:
      idx = RowIndexForUriType.propertyPrimitiveValue;
      break;
    case entitySet:
      idx = RowIndexForUriType.mediaStream;
      break;
    case function:
      UriResourceFunction uriFunction = (UriResourceFunction) secondLastPathSegment;

      EdmFunction function;
      EdmFunctionImport functionImport = uriFunction.getFunctionImport();
      if (functionImport != null) {
        List<EdmFunction> functions = functionImport.getUnboundFunctions();
        function = functions.get(0);
      } else {
        function = uriFunction.getFunction();
      }

      EdmTypeKind functionReturnTypeKind = function.getReturnType().getType().getKind();
      boolean isFunctionCollection = function.getReturnType().isCollection();
      idx = determineReturnType(functionReturnTypeKind, isFunctionCollection);
      break;
    case action:
      UriResourceAction uriAction = (UriResourceAction) secondLastPathSegment;
      EdmActionImport actionImport = uriAction.getActionImport();

      EdmAction action;
      if (actionImport != null) {
        action = actionImport.getUnboundAction();
      } else {
        action = uriAction.getAction();
      }

      EdmTypeKind actionReturnTypeKind = action.getReturnType().getType().getKind();
      boolean isActionCollection = action.getReturnType().isCollection();
      idx = determineReturnType(actionReturnTypeKind, isActionCollection);

      break;
    case navigationProperty:
      UriResourceNavigation uriNavigation = (UriResourceNavigation) secondLastPathSegment;

      if (uriNavigation.isCollection()) {
        idx = RowIndexForUriType.entitySet;
      } else {
        idx = RowIndexForUriType.entity;
      }
      break;
    case singleton:
      UriResourceSingleton uriSingleton = (UriResourceSingleton) secondLastPathSegment;
      EdmSingleton singleton = uriSingleton.getSingleton();
      EdmTypeKind singletonReturnTypeKind = singleton.getEntityType().getKind();
      idx = determineReturnType(singletonReturnTypeKind, false);
      break;
    default:
      throw new UriValidationException("Unexpected kind in path segment before $value: "
          + secondLastPathSegment.getKind(), UriValidationException.MessageKeys.UNALLOWED_KIND_BEFORE_VALUE,
          secondLastPathSegment.toString());
    }
    return idx;
  }

  private RowIndexForUriType determineReturnType(final EdmTypeKind functionReturnTypeKind,
      final boolean isCollection) throws UriValidationException {
    RowIndexForUriType idx;
    switch (functionReturnTypeKind) {
    case COMPLEX:
      idx = isCollection ? RowIndexForUriType.propertyComplexCollection : RowIndexForUriType.propertyComplex;
      break;
    case ENTITY:
      idx = isCollection ? RowIndexForUriType.entitySet : RowIndexForUriType.entity;
      break;
    case PRIMITIVE:
    case ENUM:
    case DEFINITION:
      idx = isCollection ? RowIndexForUriType.propertyPrimitiveCollection : RowIndexForUriType.propertyPrimitive;
      break;
    default:
      throw new UriValidationException("Unsupported function return type: " + functionReturnTypeKind,
          UriValidationException.MessageKeys.UNSUPPORTED_FUNCTION_RETURN_TYPE, functionReturnTypeKind.toString());
    }
    return idx;
  }

  private RowIndexForUriType rowIndexForRef(final UriInfo uriInfo, final UriResource lastPathSegment)
      throws UriValidationException {
    RowIndexForUriType idx;
    int secondLastPathSegmentIndex = uriInfo.getUriResourceParts().size() - 2;
    UriResource secondLastPathSegment = uriInfo.getUriResourceParts().get(secondLastPathSegmentIndex);

    if (secondLastPathSegment instanceof UriResourcePartTyped) {
      idx =
          ((UriResourcePartTyped) secondLastPathSegment).isCollection() ? RowIndexForUriType.references
              : RowIndexForUriType.reference;
    } else {
      throw new UriValidationException("secondLastPathSegment not a class of UriResourcePartTyped: "
          + lastPathSegment.getClass(), UriValidationException.MessageKeys.LAST_SEGMENT_NOT_TYPED, lastPathSegment
          .toString());
    }

    return idx;
  }

  private RowIndexForUriType rowIndexForPrimitiveProperty(final UriResource lastPathSegment)
      throws UriValidationException {
    RowIndexForUriType idx;
    if (lastPathSegment instanceof UriResourcePartTyped) {
      idx =
          ((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());
    }
    return idx;
  }

  private RowIndexForUriType rowIndexForFunction(final UriResource lastPathSegment) throws UriValidationException {
    RowIndexForUriType idx;
    UriResourceFunction urf = (UriResourceFunction) lastPathSegment;
    EdmReturnType rt = urf.getFunction().getReturnType();
    switch (rt.getType().getKind()) {
    case ENTITY:
      if (((EdmEntityType) rt.getType()).hasStream()) {
        idx = RowIndexForUriType.mediaStream;
      } else {
        idx = rt.isCollection() ? RowIndexForUriType.entitySet : RowIndexForUriType.entity;
      }
      break;
    case PRIMITIVE:
      idx = rt.isCollection() ? RowIndexForUriType.propertyPrimitiveCollection : RowIndexForUriType.propertyPrimitive;
      break;
    case COMPLEX:
      idx = rt.isCollection() ? RowIndexForUriType.propertyComplexCollection : RowIndexForUriType.propertyComplex;
      break;
    default:
      throw new UriValidationException("Unsupported function return type: " + rt.getType().getKind(),
          UriValidationException.MessageKeys.UNSUPPORTED_FUNCTION_RETURN_TYPE,
          rt.getType().getKind().toString());
    }

    return idx;
  }

  private RowIndexForUriType rowIndexForEntitySet(final UriResource lastPathSegment) throws UriValidationException {
    RowIndexForUriType idx;
    if (lastPathSegment instanceof UriResourcePartTyped) {
      idx =
          ((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());
    }
    return idx;
  }

  private RowIndexForUriType rowIndexForComplexProperty(final UriResource lastPathSegment)
      throws UriValidationException {
    RowIndexForUriType idx;
    if (lastPathSegment instanceof UriResourcePartTyped) {
      idx =
          ((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());
    }
    return idx;
  }

  private RowIndexForUriType rowIndexForAction(final UriResource lastPathSegment) throws UriValidationException {
    RowIndexForUriType idx;
    UriResourceAction ura = (UriResourceAction) lastPathSegment;
    EdmReturnType rt = ura.getAction().getReturnType();
    switch (rt.getType().getKind()) {
    case ENTITY:
      if (((EdmEntityType) rt.getType()).hasStream()) {
        idx = RowIndexForUriType.mediaStream;
      } else {
        idx = rt.isCollection() ? RowIndexForUriType.entitySet : RowIndexForUriType.entity;
      }
      break;
    case PRIMITIVE:
      idx = rt.isCollection() ? RowIndexForUriType.propertyPrimitiveCollection : RowIndexForUriType.propertyPrimitive;
      break;
    case COMPLEX:
      idx = rt.isCollection() ? RowIndexForUriType.propertyComplexCollection : RowIndexForUriType.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;
  }

  private RowIndexForUriType rowIndexForCount(final UriInfo uriInfo) throws UriValidationException {

    RowIndexForUriType idx;
    int secondLastPathSegmentIndex = uriInfo.getUriResourceParts().size() - 2;
    UriResource secondLastPathSegment = uriInfo.getUriResourceParts().get(secondLastPathSegmentIndex);
    switch (secondLastPathSegment.getKind()) {
    case entitySet:
    case navigationProperty:
      idx = RowIndexForUriType.entitySetCount;
      break;
    case complexProperty:
      idx = RowIndexForUriType.propertyComplexCollectionCount;
      break;
    case primitiveProperty:
      idx = RowIndexForUriType.propertyPrimitiveCollectionCount;
      break;
    case function:
      UriResourceFunction uriFunction = (UriResourceFunction) secondLastPathSegment;

      EdmFunction function;
      List<EdmFunction> functions;
      EdmFunctionImport functionImport = uriFunction.getFunctionImport();
      if (functionImport != null) {
        functions = functionImport.getUnboundFunctions();
        function = functions.get(0);
      } else {
        function = uriFunction.getFunction();
      }

      EdmTypeKind functionReturnTypeKind = function.getReturnType().getType().getKind();
      boolean isCollection = function.getReturnType().isCollection();
      idx = determineReturnType(functionReturnTypeKind, isCollection);
      break;
    default:
      throw new UriValidationException("Illegal path part kind before $count: " + secondLastPathSegment.getKind(),
          UriValidationException.MessageKeys.UNALLOWED_KIND_BEFORE_COUNT, secondLastPathSegment.toString());
    }

    return idx;
  }

  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 {
    RowIndexForHttpMethod row = rowIndexForHttpMethod(httpMethod);

    for (SystemQueryOption option : uriInfo.getSystemQueryOptions()) {
      ColumnIndex col = colIndex(option.getKind());
      if (!decisionMatrixForHttpMethod[row.getIndex()][col.getIndex()]) {
        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 RowIndexForHttpMethod rowIndexForHttpMethod(final HttpMethod httpMethod) throws UriValidationException {
    RowIndexForHttpMethod idx;

    switch (httpMethod) {
    case GET:
      idx = RowIndexForHttpMethod.GET;
      break;
    case POST:
      idx = RowIndexForHttpMethod.POST;
      break;
    case PUT:
      idx = RowIndexForHttpMethod.PUT;
      break;
    case DELETE:
      idx = RowIndexForHttpMethod.DELETE;
      break;
    case PATCH:
      idx = RowIndexForHttpMethod.PATCH;
      break;
    default:
      throw new UriValidationException("HTTP method not supported: " + httpMethod,
          UriValidationException.MessageKeys.UNSUPPORTED_HTTP_METHOD, httpMethod.toString());
    }

    return idx;
  }

  private void validateKeyPredicates(final UriInfo uriInfo) throws UriValidationException {
    for (UriResource pathSegment : uriInfo.getUriResourceParts()) {
      if (pathSegment.getKind() == UriResourceKind.entitySet) {
        UriResourceEntitySet pathEntitySet = (UriResourceEntitySet) pathSegment;
        List<UriParameter> keyPredicates = pathEntitySet.getKeyPredicates();

        if (keyPredicates != null) {

          final List<String> keyPredicateNames = pathEntitySet.getEntityType().getKeyPredicateNames();
          HashMap<String, EdmKeyPropertyRef> edmKeys = new HashMap<String, EdmKeyPropertyRef>();
          for (EdmKeyPropertyRef key : pathEntitySet.getEntityType().getKeyPropertyRefs()) {
            edmKeys.put(key.getKeyPropertyName(), 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();
            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())) {
                // TODO: Check exception here
                throw new UriValidationException("PrimitiveTypeException",
                    UriValidationException.MessageKeys.INVALID_KEY_PROPERTY, name);
              }
            } catch (EdmPrimitiveTypeException e) {
              // TODO: Check exception here
              throw new UriValidationException("PrimitiveTypeException", e,
                  UriValidationException.MessageKeys.INVALID_KEY_PROPERTY, name);
            }

            edmKeys.remove(name);
            edmKeys.remove(alias);
          }
        }
      }
    }
  }

  private void validatePropertyOperations(final UriInfo uriInfo, final HttpMethod method)
      throws UriValidationException {
    final List<UriResource> parts = uriInfo.getUriResourceParts();
    final UriResource last = parts.size() > 0 ? parts.get(parts.size() - 1) : null;
    final UriResource previous = parts.size() > 1 ? parts.get(parts.size() - 2) : null;
    if (last != null
        && (last.getKind() == UriResourceKind.primitiveProperty
        || last.getKind() == UriResourceKind.complexProperty
        || last.getKind() == UriResourceKind.value && previous.getKind() == UriResourceKind.primitiveProperty)) {
      final EdmProperty property = ((UriResourceProperty)
          (last.getKind() == UriResourceKind.value ? previous : last)).getProperty();
      if (method == HttpMethod.PATCH && property.isCollection()) {
        throw new UriValidationException("Attempt to patch collection property.",
            UriValidationException.MessageKeys.UNSUPPORTED_HTTP_METHOD, method.toString());
      }
      if (method == HttpMethod.DELETE && property.isNullable() != null && !property.isNullable()) {
        throw new UriValidationException("Attempt to delete non-nullable property.",
            UriValidationException.MessageKeys.UNSUPPORTED_HTTP_METHOD, method.toString());
      }
    }
  }
}
