olingo-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From chri...@apache.org
Subject [17/30] olingo-odata4 git commit: [OLINGO-834] ExpressionParser parses path expressions
Date Tue, 12 Jan 2016 13:08:18 GMT
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a8091658/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 2a994d3..118c649 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
@@ -46,29 +46,22 @@ 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.FilterOption;
 import org.apache.olingo.server.api.uri.queryoption.QueryOption;
 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.UriResourceTypedImpl;
-import org.apache.olingo.server.core.uri.UriResourceWithKeysImpl;
 import org.apache.olingo.server.core.uri.antlr.UriLexer;
 import org.apache.olingo.server.core.uri.antlr.UriParserParser;
 import org.apache.olingo.server.core.uri.antlr.UriParserParser.ExpandItemsEOFContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.FilterExpressionEOFContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.OrderByEOFContext;
 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.SkipOptionImpl;
 import org.apache.olingo.server.core.uri.queryoption.SkipTokenOptionImpl;
 import org.apache.olingo.server.core.uri.queryoption.TopOptionImpl;
@@ -84,9 +77,7 @@ public class Parser {
   private final Edm edm;
   private final OData odata;
 
-  private enum ParserEntryRules {
-    ExpandItems, FilterExpression, Orderby
-  }
+  private enum ParserEntryRules { ExpandItems }
 
   public Parser(final Edm edm, final OData odata) {
     this.edm = edm;
@@ -131,7 +122,7 @@ public class Parser {
       if (numberOfSegments > 1) {
         final String typeCastSegment = pathSegmentsDecoded.get(1);
         ensureLastSegment(typeCastSegment, 2, numberOfSegments);
-        context.contextUriInfo = new ResourcePathParser(edm, odata).parseDollarEntityTypeCast(typeCastSegment);
+        context.contextUriInfo = new ResourcePathParser(edm).parseDollarEntityTypeCast(typeCastSegment);
         context.contextTypes.push(context.contextUriInfo.getEntityTypeCast());
       } else {
         context.contextUriInfo = new UriInfoImpl().setKind(UriInfoKind.entityId);
@@ -141,7 +132,7 @@ public class Parser {
 
     } else if (firstSegment.startsWith("$crossjoin")) {
       ensureLastSegment(firstSegment, 1, numberOfSegments);
-      context.contextUriInfo = new ResourcePathParser(edm, odata).parseCrossjoinSegment(firstSegment);
+      context.contextUriInfo = new ResourcePathParser(edm).parseCrossjoinSegment(firstSegment);
       final EdmEntityContainer container = edm.getEntityContainer();
       for (final String name : context.contextUriInfo.getEntitySetNames()) {
         context.contextTypes.push(container.getEntitySet(name).getEntityType());
@@ -150,7 +141,7 @@ public class Parser {
 
     } else {
       context.contextUriInfo = new UriInfoImpl().setKind(UriInfoKind.resource);
-      final ResourcePathParser resourcePathParser = new ResourcePathParser(edm, odata);
+      final ResourcePathParser resourcePathParser = new ResourcePathParser(edm);
       int count = 0;
       UriResource lastSegment = null;
       for (final String pathSegment : pathSegmentsDecoded) {
@@ -183,7 +174,7 @@ public class Parser {
 
       if (lastSegment instanceof UriResourcePartTyped) {
         final UriResourcePartTyped typed = (UriResourcePartTyped) lastSegment;
-        final EdmType type = getTypeInformation(typed);
+        final EdmType type = ParserHelper.getTypeInformation(typed);
         if (type != null) { // could be null for, e.g., actions without return type
           context.contextTypes.push(type);
         }
@@ -199,23 +190,13 @@ public class Parser {
       if (optionName.startsWith("$")) {
         SystemQueryOption systemOption = null;
         if (optionName.equals(SystemQueryOptionKind.FILTER.toString())) {
-          try {
-            FilterExpressionEOFContext ctxFilterExpression =
-                (FilterExpressionEOFContext) parseRule(optionValue, ParserEntryRules.FilterExpression);
-            systemOption = (FilterOptionImpl) uriParseTreeVisitor.visitFilterExpressionEOF(ctxFilterExpression);
-          } catch (final ParseCancellationException e) {
-            throw e.getCause() instanceof UriParserException ?
-                (UriParserException) e.getCause() :
-                new UriParserSyntaxException("Syntax error", e, UriParserSyntaxException.MessageKeys.SYNTAX);
-          }
-//          UriTokenizer filterTokenizer = new UriTokenizer(optionValue);
-//          systemOption = new FilterOptionImpl().setExpression(
-//              new ExpressionParser().parse(filterTokenizer));
-//          if (!filterTokenizer.next(TokenKind.EOF)) {
-//            throw new UriParserSyntaxException("Illegal value of $filter option!",
-//                UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION,
-//                optionName, optionValue);
-//          }
+          UriTokenizer filterTokenizer = new UriTokenizer(optionValue);
+          systemOption = new FilterParser(edm, odata).parse(filterTokenizer,
+              context.contextTypes.peek() instanceof EdmStructuredType ?
+                  (EdmStructuredType) context.contextTypes.peek() :
+                  null,
+                  context.contextUriInfo.getEntitySetNames());
+          checkOptionEOF(filterTokenizer, optionName, optionValue);
 
         } else if (optionName.equals(SystemQueryOptionKind.FORMAT.toString())) {
           FormatOptionImpl formatOption = new FormatOptionImpl();
@@ -253,15 +234,13 @@ public class Parser {
               UriParserSyntaxException.MessageKeys.SYSTEM_QUERY_OPTION_LEVELS_NOT_ALLOWED_HERE);
 
         } else if (optionName.equals(SystemQueryOptionKind.ORDERBY.toString())) {
-          try {
-            OrderByEOFContext ctxOrderByExpression =
-                (OrderByEOFContext) parseRule(optionValue, ParserEntryRules.Orderby);
-            systemOption = (OrderByOptionImpl) uriParseTreeVisitor.visitOrderByEOF(ctxOrderByExpression);
-          } catch (final ParseCancellationException e) {
-            throw e.getCause() instanceof UriParserException ?
-                (UriParserException) e.getCause() :
-                new UriParserSyntaxException("Syntax error", e, UriParserSyntaxException.MessageKeys.SYNTAX);
-          }
+          UriTokenizer orderByTokenizer = new UriTokenizer(optionValue);
+          systemOption = new OrderByParser(edm, odata).parse(orderByTokenizer,
+              context.contextTypes.peek() instanceof EdmStructuredType ?
+                  (EdmStructuredType) context.contextTypes.peek() :
+                  null,
+                  context.contextUriInfo.getEntitySetNames());
+          checkOptionEOF(orderByTokenizer, optionName, optionValue);
 
         } else if (optionName.equals(SystemQueryOptionKind.SEARCH.toString())) {
           systemOption = new SearchParser().parse(optionValue);
@@ -273,11 +252,7 @@ public class Parser {
                   (EdmStructuredType) context.contextTypes.peek() :
                   null,
               context.isCollection);
-          if (!selectTokenizer.next(TokenKind.EOF)) {
-            throw new UriParserSyntaxException("Illegal value of $select option!",
-                UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION,
-                optionName, optionValue);
-          }
+          checkOptionEOF(selectTokenizer, optionName, optionValue);
 
         } else if (optionName.equals(SystemQueryOptionKind.SKIP.toString())) {
           SkipOptionImpl skipOption = new SkipOptionImpl();
@@ -343,15 +318,12 @@ public class Parser {
                   UriParserSyntaxException.MessageKeys.SYNTAX);
             }
           } else {
-            try {
-              final FilterExpressionEOFContext filterExpCtx =
-                  (FilterExpressionEOFContext) parseRule(optionValue, ParserEntryRules.FilterExpression);
-              expression = ((FilterOption) uriParseTreeVisitor.visitFilterExpressionEOF(filterExpCtx))
-                  .getExpression();
-            } catch (final ParseCancellationException e) {
-              throw e.getCause() instanceof UriParserException ?
-                  (UriParserException) e.getCause() :
-                  new UriParserSyntaxException("Syntax error", e, UriParserSyntaxException.MessageKeys.SYNTAX);
+            UriTokenizer aliasValueTokenizer = new UriTokenizer(optionValue);
+            expression = new ExpressionParser(edm, odata).parse(aliasValueTokenizer, null,
+                context.contextUriInfo.getEntitySetNames());
+            if (!aliasValueTokenizer.next(TokenKind.EOF)) {
+              throw new UriParserSyntaxException("Illegal value for alias '" + optionName + "'.",
+                  UriParserSyntaxException.MessageKeys.SYNTAX);
             }
           }
           context.contextUriInfo.addAlias((AliasQueryOption) new AliasQueryOptionImpl()
@@ -384,28 +356,13 @@ public class Parser {
     return index > 0 && index < value.length() - 1 && index == value.lastIndexOf('/');
   }
 
-  protected static EdmType getTypeInformation(final UriResourcePartTyped resourcePart) {
-    EdmType type = null;
-    if (resourcePart instanceof UriResourceWithKeysImpl) {
-      final UriResourceWithKeysImpl lastPartWithKeys = (UriResourceWithKeysImpl) resourcePart;
-      if (lastPartWithKeys.getTypeFilterOnEntry() != null) {
-        type = lastPartWithKeys.getTypeFilterOnEntry();
-      } else if (lastPartWithKeys.getTypeFilterOnCollection() != null) {
-        type = lastPartWithKeys.getTypeFilterOnCollection();
-      } else {
-        type = lastPartWithKeys.getType();
-      }
-
-    } else if (resourcePart instanceof UriResourceTypedImpl) {
-      final UriResourceTypedImpl lastPartTyped = (UriResourceTypedImpl) resourcePart;
-      type = lastPartTyped.getTypeFilter() == null ?
-          lastPartTyped.getType() :
-          lastPartTyped.getTypeFilter();
-    } else {
-      type = resourcePart.getType();
+  private void checkOptionEOF(UriTokenizer tokenizer, final String optionName, final String optionValue)
+      throws UriParserException {
+    if (!tokenizer.next(TokenKind.EOF)) {
+      throw new UriParserSyntaxException("Illegal value of '" + optionName + "' option!",
+          UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION,
+          optionName, optionValue);
     }
-
-    return type;
   }
 
   private ParserRuleContext parseRule(final String input, final ParserEntryRules entryPoint)
@@ -435,14 +392,6 @@ public class Parser {
 
       // parse
       switch (entryPoint) {
-      case FilterExpression:
-        lexer.mode(Lexer.DEFAULT_MODE);
-        ret = parser.filterExpressionEOF();
-        break;
-      case Orderby:
-        lexer.mode(Lexer.DEFAULT_MODE);
-        ret = parser.orderByEOF();
-        break;
       case ExpandItems:
         lexer.mode(Lexer.DEFAULT_MODE);
         ret = parser.expandItemsEOF();
@@ -471,14 +420,6 @@ public class Parser {
 
         // parse
         switch (entryPoint) {
-        case FilterExpression:
-          lexer.mode(Lexer.DEFAULT_MODE);
-          ret = parser.filterExpressionEOF();
-          break;
-        case Orderby:
-          lexer.mode(Lexer.DEFAULT_MODE);
-          ret = parser.orderByEOF();
-          break;
         case ExpandItems:
           lexer.mode(Lexer.DEFAULT_MODE);
           ret = parser.expandItemsEOF();

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a8091658/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 e811575..65ee461 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
@@ -18,10 +18,35 @@
  */
 package org.apache.olingo.server.core.uri.parser;
 
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.commons.api.edm.EdmEntityType;
+import org.apache.olingo.commons.api.edm.EdmKeyPropertyRef;
+import org.apache.olingo.commons.api.edm.EdmNavigationProperty;
+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.EdmType;
+import org.apache.olingo.commons.api.edm.EdmTypeDefinition;
+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.core.ODataImpl;
+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.validator.UriValidationException;
 
 public class ParserHelper {
 
+  private static final OData odata = new ODataImpl();
+
   public static void requireNext(UriTokenizer tokenizer, final TokenKind required) throws UriParserException {
     if (!tokenizer.next(required)) {
       throw new UriParserSyntaxException("Expected token '" + required.toString() + "' not found.",
@@ -33,16 +58,16 @@ public class ParserHelper {
     requireNext(tokenizer, TokenKind.EOF);
   }
 
-  public static TokenKind next(UriTokenizer tokenizer, final TokenKind... kind) {
-    for (int i = 0; i < kind.length; i++) {
-      if (tokenizer.next(kind[i])) {
-        return kind[i];
+  public static TokenKind next(UriTokenizer tokenizer, final TokenKind... kinds) {
+    for (final TokenKind kind : kinds) {
+      if (tokenizer.next(kind)) {
+        return kind;
       }
     }
     return null;
   }
 
-  public static TokenKind nextPrimitive(UriTokenizer tokenizer) {
+  public static TokenKind nextPrimitiveValue(UriTokenizer tokenizer) {
     return next(tokenizer,
         TokenKind.NULL,
         TokenKind.BooleanValue,
@@ -62,4 +87,304 @@ public class ParserHelper {
         TokenKind.BinaryValue,
         TokenKind.EnumValue);
   }
+
+  protected static List<UriParameter> parseFunctionParameters(UriTokenizer tokenizer, final boolean withComplex)
+      throws UriParserException {
+    List<UriParameter> parameters = new ArrayList<UriParameter>();
+    ParserHelper.requireNext(tokenizer, TokenKind.OPEN);
+    if (tokenizer.next(TokenKind.CLOSE)) {
+      return parameters;
+    }
+    do {
+      ParserHelper.requireNext(tokenizer, TokenKind.ODataIdentifier);
+      final String name = tokenizer.getText();
+      if (parameters.contains(name)) {
+        throw new UriParserSemanticException("Duplicated function parameter " + name,
+            UriParserSemanticException.MessageKeys.INVALID_KEY_VALUE, name);
+      }
+      ParserHelper.requireNext(tokenizer, TokenKind.EQ);
+      if (tokenizer.next(TokenKind.COMMA) || tokenizer.next(TokenKind.CLOSE) || tokenizer.next(TokenKind.EOF)) {
+        throw new UriParserSyntaxException("Parameter value expected.", UriParserSyntaxException.MessageKeys.SYNTAX);
+      }
+      if (tokenizer.next(TokenKind.ParameterAliasName)) {
+        parameters.add(new UriParameterImpl().setName(name).setAlias(tokenizer.getText()));
+      } else if (tokenizer.next(TokenKind.jsonArrayOrObject)) {
+        if (withComplex) {
+          parameters.add(new UriParameterImpl().setName(name).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 (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));
+      }
+    } while (tokenizer.next(TokenKind.COMMA));
+    ParserHelper.requireNext(tokenizer, TokenKind.CLOSE);
+    return parameters;
+  }
+
+  protected static List<UriParameter> parseNavigationKeyPredicate(UriTokenizer tokenizer,
+      final EdmNavigationProperty navigationProperty) throws UriParserException, UriValidationException {
+    if (tokenizer.next(TokenKind.OPEN)) {
+      if (navigationProperty.isCollection()) {
+        return parseKeyPredicate(tokenizer, navigationProperty.getType(), navigationProperty.getPartner());
+      } else {
+        throw new UriParserSemanticException("A key is not allowed on non-collection navigation properties.",
+            UriParserSemanticException.MessageKeys.KEY_NOT_ALLOWED);
+      }
+    }
+    return null;
+  }
+
+  protected static List<UriParameter> parseKeyPredicate(UriTokenizer tokenizer, final EdmEntityType edmEntityType,
+      final EdmNavigationProperty partner) throws UriParserException, UriValidationException {
+    final List<EdmKeyPropertyRef> keyPropertyRefs = edmEntityType.getKeyPropertyRefs();
+    if (tokenizer.next(TokenKind.CLOSE)) {
+      throw new UriParserSemanticException(
+          "Expected " + keyPropertyRefs.size() + " key predicates but none.",
+          UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES,
+          Integer.toString(keyPropertyRefs.size()), "0");
+    }
+    List<UriParameter> keys = new ArrayList<UriParameter>();
+    Map<String, String> referencedNames = new HashMap<String, String>();
+
+    if (partner != null) {
+      // Prepare list of potentially missing keys to be filled from referential constraints.
+      for (final String name : edmEntityType.getKeyPredicateNames()) {
+        final String referencedName = partner.getReferencingPropertyName(name);
+        if (referencedName != null) {
+          referencedNames.put(name, referencedName);
+        }
+      }
+    }
+
+    if (tokenizer.next(TokenKind.ODataIdentifier)) {
+      keys.addAll(compoundKey(tokenizer, edmEntityType));
+    } else if (keyPropertyRefs.size() - referencedNames.size() == 1) {
+      for (final EdmKeyPropertyRef candidate : keyPropertyRefs) {
+        if (referencedNames.get(candidate.getName()) == null) {
+          keys.add(simpleKey(tokenizer, candidate));
+          break;
+        }
+      }
+    } else {
+      throw new UriParserSemanticException(
+          "Expected " + (keyPropertyRefs.size() -referencedNames.size()) + " key predicates but found one.",
+          UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES,
+          Integer.toString(keyPropertyRefs.size() - referencedNames.size()), "1");
+    }
+
+    if (keys.size() < keyPropertyRefs.size() && partner != null) {
+      // Fill missing keys from referential constraints.
+      for (final String name : edmEntityType.getKeyPredicateNames()) {
+        boolean found = false;
+        for (final UriParameter key : keys) {
+          if (name.equals(key.getName())) {
+            found = true;
+            break;
+          }
+        }
+        if (!found && referencedNames.get(name) != null) {
+          keys.add(0, new UriParameterImpl().setName(name).setReferencedProperty(referencedNames.get(name)));
+        }
+      }
+    }
+
+    // Check that all key predicates are filled from the URI.
+    if (keys.size() < keyPropertyRefs.size()) {
+      throw new UriParserSemanticException(
+          "Expected " + keyPropertyRefs.size() + " key predicates but found " + keys.size() + ".",
+          UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES,
+          Integer.toString(keyPropertyRefs.size()), Integer.toString(keys.size()));
+    } else {
+      return keys;
+    }
+  }
+
+  private static UriParameter simpleKey(UriTokenizer tokenizer, final EdmKeyPropertyRef edmKeyPropertyRef)
+      throws UriParserException, UriValidationException {
+    final EdmProperty edmProperty = edmKeyPropertyRef == null ? null : edmKeyPropertyRef.getProperty();
+    if (nextPrimitiveTypeValue(tokenizer,
+        edmProperty == null ? null : (EdmPrimitiveType) edmProperty.getType(),
+        edmProperty == null ? false : edmProperty.isNullable())) {
+      final String literalValue = tokenizer.getText();
+      ParserHelper.requireNext(tokenizer, TokenKind.CLOSE);
+      return createUriParameter(edmProperty, edmKeyPropertyRef.getName(), literalValue);
+    } 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)
+      throws UriParserException, UriValidationException {
+
+    List<UriParameter> parameters = new ArrayList<UriParameter>();
+    List<String> parameterNames = new ArrayList<String>();
+
+    // To validate that each key predicate is exactly specified once, we use a list to pick from.
+    List<String> remainingKeyNames = new ArrayList<String>(edmEntityType.getKeyPredicateNames());
+
+    // At least one key predicate is mandatory.  Try to fetch all.
+    boolean hasComma = false;
+    do {
+      final String keyPredicateName = tokenizer.getText();
+      if (parameterNames.contains(keyPredicateName)) {
+        throw new UriValidationException("Duplicated key property " + keyPredicateName,
+            UriValidationException.MessageKeys.DOUBLE_KEY_PROPERTY, keyPredicateName);
+      }
+      if (remainingKeyNames.isEmpty()) {
+        throw new UriParserSemanticException("Too many key properties.",
+            UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES,
+            Integer.toString(parameters.size()), Integer.toString(parameters.size() + 1));
+      }
+      if (!remainingKeyNames.remove(keyPredicateName)) {
+        throw new UriValidationException("Unknown key property " + keyPredicateName,
+            UriValidationException.MessageKeys.INVALID_KEY_PROPERTY, keyPredicateName);
+      }
+      parameters.add(keyValuePair(tokenizer, keyPredicateName, edmEntityType));
+      parameterNames.add(keyPredicateName);
+      hasComma = tokenizer.next(TokenKind.COMMA);
+      if (hasComma) {
+        ParserHelper.requireNext(tokenizer, TokenKind.ODataIdentifier);
+      }
+    } while (hasComma);
+    ParserHelper.requireNext(tokenizer, TokenKind.CLOSE);
+
+    return parameters;
+  }
+
+  protected static UriParameter keyValuePair(UriTokenizer tokenizer,
+      final String keyPredicateName, final EdmEntityType edmEntityType)
+      throws UriParserException, UriValidationException {
+    final EdmKeyPropertyRef keyPropertyRef = edmEntityType.getKeyPropertyRef(keyPredicateName);
+    final EdmProperty edmProperty = keyPropertyRef == null ? null : keyPropertyRef.getProperty();
+    if (edmProperty == null) {
+      throw new UriValidationException(keyPredicateName + " is not a valid key property name.",
+          UriValidationException.MessageKeys.INVALID_KEY_PROPERTY, keyPredicateName);
+    }
+    ParserHelper.requireNext(tokenizer, TokenKind.EQ);
+    if (tokenizer.next(TokenKind.COMMA) || tokenizer.next(TokenKind.CLOSE) || tokenizer.next(TokenKind.EOF)) {
+      throw new UriParserSyntaxException("Key value expected.", UriParserSyntaxException.MessageKeys.SYNTAX);
+    }
+    if (nextPrimitiveTypeValue(tokenizer, (EdmPrimitiveType) edmProperty.getType(), edmProperty.isNullable())) {
+      return createUriParameter(edmProperty, keyPredicateName, tokenizer.getText());
+    } else {
+      throw new UriParserSemanticException(keyPredicateName + " has not a valid  key value.",
+          UriParserSemanticException.MessageKeys.INVALID_KEY_VALUE, keyPredicateName);
+    }
+  }
+
+  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 EdmPrimitiveType primitiveType = (EdmPrimitiveType) edmProperty.getType();
+    try {
+      if (!(primitiveType.validate(primitiveType.fromUriLiteral(literalValue), 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",
+          UriValidationException.MessageKeys.INVALID_KEY_PROPERTY, parameterName);
+    }
+
+    return new UriParameterImpl()
+        .setName(parameterName)
+        .setText("null".equals(literalValue) ? null : literalValue);
+  }
+
+  private static boolean nextPrimitiveTypeValue(UriTokenizer tokenizer,
+      final EdmPrimitiveType primitiveType, final boolean nullable) {
+    final EdmPrimitiveType type = primitiveType instanceof EdmTypeDefinition ?
+        ((EdmTypeDefinition) primitiveType).getUnderlyingType() :
+        primitiveType;
+    if (tokenizer.next(TokenKind.ParameterAliasName)) {
+      return true;
+    } else if (nullable && tokenizer.next(TokenKind.NULL)) {
+      return true;
+
+    } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Boolean).equals(type)) {
+      return tokenizer.next(TokenKind.BooleanValue);
+    } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.String).equals(type)) {
+      return tokenizer.next(TokenKind.StringValue);
+    } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.SByte).equals(type)
+        || odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Byte).equals(type)
+        || odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Int16).equals(type)
+        || odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Int32).equals(type)
+        || odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Int64).equals(type)) {
+      return tokenizer.next(TokenKind.IntegerValue);
+    } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Guid).equals(type)) {
+      return tokenizer.next(TokenKind.GuidValue);
+    } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Date).equals(type)) {
+      return tokenizer.next(TokenKind.DateValue);
+    } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.DateTimeOffset).equals(type)) {
+      return tokenizer.next(TokenKind.DateTimeOffsetValue);
+    } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.TimeOfDay).equals(type)) {
+      return tokenizer.next(TokenKind.TimeOfDayValue);
+    } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Decimal).equals(type)) {
+      // The order is important.
+      // A decimal value should not be parsed as integer and let the tokenizer stop at the decimal point.
+      return tokenizer.next(TokenKind.DecimalValue)
+          || tokenizer.next(TokenKind.IntegerValue);
+    } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Double).equals(type)) {
+      // The order is important.
+      // A floating-point value should not be parsed as decimal and let the tokenizer stop at 'E'.
+      // A decimal value should not be parsed as integer and let the tokenizer stop at the decimal point.
+      return tokenizer.next(TokenKind.DoubleValue)
+          || tokenizer.next(TokenKind.DecimalValue)
+          || tokenizer.next(TokenKind.IntegerValue);
+    } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Duration).equals(type)) {
+      return tokenizer.next(TokenKind.DurationValue);
+    } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Binary).equals(type)) {
+      return tokenizer.next(TokenKind.BinaryValue);
+    } else if (type.getKind() == EdmTypeKind.ENUM) {
+      return tokenizer.next(TokenKind.EnumValue);
+    } else {
+      return false;
+    }
+  }
+
+  protected static List<String> getParameterNames(final List<UriParameter> parameters) {
+    List<String> names = new ArrayList<String>();
+    for (final UriParameter parameter : parameters) {
+      names.add(parameter.getName());
+    }
+    return names;
+  }
+
+  protected static EdmType getTypeInformation(final UriResourcePartTyped resourcePart) {
+    EdmType type = null;
+    if (resourcePart instanceof UriResourceWithKeysImpl) {
+      final UriResourceWithKeysImpl lastPartWithKeys = (UriResourceWithKeysImpl) resourcePart;
+      if (lastPartWithKeys.getTypeFilterOnEntry() != null) {
+        type = lastPartWithKeys.getTypeFilterOnEntry();
+      } else if (lastPartWithKeys.getTypeFilterOnCollection() != null) {
+        type = lastPartWithKeys.getTypeFilterOnCollection();
+      } else {
+        type = lastPartWithKeys.getType();
+      }
+
+    } else if (resourcePart instanceof UriResourceTypedImpl) {
+      final UriResourceTypedImpl lastPartTyped = (UriResourceTypedImpl) resourcePart;
+      type = lastPartTyped.getTypeFilter() == null ?
+          lastPartTyped.getType() :
+          lastPartTyped.getTypeFilter();
+    } else {
+      type = resourcePart.getType();
+    }
+
+    return type;
+  }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a8091658/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 5d2fbde..1cd4d7a 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,10 +18,7 @@
  */
 package org.apache.olingo.server.core.uri.parser;
 
-import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 
 import org.apache.olingo.commons.api.edm.Edm;
 import org.apache.olingo.commons.api.edm.EdmAction;
@@ -31,25 +28,18 @@ import org.apache.olingo.commons.api.edm.EdmEntitySet;
 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.EdmNavigationProperty;
-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.EdmSingleton;
 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.server.api.OData;
 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.core.uri.UriParameterImpl;
 import org.apache.olingo.server.core.uri.UriResourceActionImpl;
 import org.apache.olingo.server.core.uri.UriResourceComplexPropertyImpl;
 import org.apache.olingo.server.core.uri.UriResourceCountImpl;
@@ -69,13 +59,11 @@ public class ResourcePathParser {
 
   private final Edm edm;
   private final EdmEntityContainer edmEntityContainer;
-  private final OData odata;
   private UriTokenizer tokenizer;
 
-  public ResourcePathParser(final Edm edm, final OData odata) {
+  public ResourcePathParser(final Edm edm) {
     this.edm = edm;
     edmEntityContainer = edm.getEntityContainer();
-    this.odata = odata;
   }
 
   public UriResource parsePathSegment(final String pathSegment, UriResource previous)
@@ -188,10 +176,11 @@ public class ResourcePathParser {
 
     final EdmEntitySet edmEntitySet = edmEntityContainer.getEntitySet(oDataIdentifier);
     if (edmEntitySet != null) {
-      final UriResourceEntitySetImpl entitySetResource = new UriResourceEntitySetImpl().setEntitSet(edmEntitySet);
+      final UriResourceEntitySetImpl entitySetResource = new UriResourceEntitySetImpl(edmEntitySet);
 
       if (tokenizer.next(TokenKind.OPEN)) {
-        final List<UriParameter> keyPredicates = keyPredicate(entitySetResource.getEntityType(), null);
+        final List<UriParameter> keyPredicates =
+            ParserHelper.parseKeyPredicate(tokenizer, entitySetResource.getEntityType(), null);
         entitySetResource.setKeyPredicates(keyPredicates);
       }
 
@@ -202,13 +191,13 @@ public class ResourcePathParser {
     final EdmSingleton edmSingleton = edmEntityContainer.getSingleton(oDataIdentifier);
     if (edmSingleton != null) {
       ParserHelper.requireTokenEnd(tokenizer);
-      return new UriResourceSingletonImpl().setSingleton(edmSingleton);
+      return new UriResourceSingletonImpl(edmSingleton);
     }
 
     final EdmActionImport edmActionImport = edmEntityContainer.getActionImport(oDataIdentifier);
     if (edmActionImport != null) {
       ParserHelper.requireTokenEnd(tokenizer);
-      return new UriResourceActionImpl().setActionImport(edmActionImport);
+      return new UriResourceActionImpl(edmActionImport);
     }
 
     final EdmFunctionImport edmFunctionImport = edmEntityContainer.getFunctionImport(oDataIdentifier);
@@ -252,8 +241,8 @@ public class ResourcePathParser {
       return property.isPrimitive()
           || property.getType().getKind() == EdmTypeKind.ENUM
           || property.getType().getKind() == EdmTypeKind.DEFINITION ?
-          new UriResourcePrimitivePropertyImpl().setProperty(property) :
-          new UriResourceComplexPropertyImpl().setProperty(property);
+          new UriResourcePrimitivePropertyImpl(property) :
+          new UriResourceComplexPropertyImpl(property);
     }
     final EdmNavigationProperty navigationProperty = structType.getNavigationProperty(name);
     if (navigationProperty == null) {
@@ -262,18 +251,9 @@ public class ResourcePathParser {
           UriParserSemanticException.MessageKeys.PROPERTY_NOT_IN_TYPE,
           structType.getFullQualifiedName().getFullQualifiedNameAsString(), name);
     }
-    List<UriParameter> keyPredicate = null;
-    if (tokenizer.next(TokenKind.OPEN)) {
-      if (navigationProperty.isCollection()) {
-        keyPredicate = keyPredicate(navigationProperty.getType(), navigationProperty.getPartner());
-      } else {
-        throw new UriParserSemanticException("A key is not allowed on non-collection navigation properties.",
-            UriParserSemanticException.MessageKeys.KEY_NOT_ALLOWED);
-      }
-    }
+    List<UriParameter> keyPredicate = ParserHelper.parseNavigationKeyPredicate(tokenizer, navigationProperty);
     ParserHelper.requireTokenEnd(tokenizer);
-    return new UriResourceNavigationPropertyImpl()
-        .setNavigationProperty(navigationProperty)
+    return new UriResourceNavigationPropertyImpl(navigationProperty)
         .setKeyPredicates(keyPredicate);
   }
 
@@ -289,7 +269,7 @@ public class ResourcePathParser {
           previousTyped.isCollection());
       if (boundAction != null) {
         ParserHelper.requireTokenEnd(tokenizer);
-        return new UriResourceActionImpl().setAction(boundAction);
+        return new UriResourceActionImpl(boundAction);
       }
       EdmStructuredType type = edm.getEntityType(name);
       if (type == null) {
@@ -314,169 +294,6 @@ public class ResourcePathParser {
     }
   }
 
-  private List<UriParameter> keyPredicate(final EdmEntityType edmEntityType, final EdmNavigationProperty partner)
-      throws UriParserException, UriValidationException {
-    final List<EdmKeyPropertyRef> keyPropertyRefs = edmEntityType.getKeyPropertyRefs();
-    if (tokenizer.next(TokenKind.CLOSE)) {
-      throw new UriParserSemanticException(
-          "Expected " + keyPropertyRefs.size() + " key predicates but none.",
-          UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES,
-          Integer.toString(keyPropertyRefs.size()), "0");
-    }
-    List<UriParameter> keys = new ArrayList<UriParameter>();
-    Map<String, String> referencedNames = new HashMap<String, String>();
-
-    if (partner != null) {
-      // Prepare list of potentially missing keys to be filled from referential constraints.
-      for (final String name : edmEntityType.getKeyPredicateNames()) {
-        final String referencedName = partner.getReferencingPropertyName(name);
-        if (referencedName != null) {
-          referencedNames.put(name, referencedName);
-        }
-      }
-    }
-
-    if (tokenizer.next(TokenKind.ODataIdentifier)) {
-      keys.addAll(compoundKey(edmEntityType));
-    } else if (keyPropertyRefs.size() - referencedNames.size() == 1) {
-      for (final EdmKeyPropertyRef candidate : keyPropertyRefs) {
-        if (referencedNames.get(candidate.getName()) == null) {
-          keys.add(simpleKey(candidate));
-          break;
-        }
-      }
-    } else {
-      throw new UriParserSemanticException(
-          "Expected " + (keyPropertyRefs.size() -referencedNames.size()) + " key predicates but found one.",
-          UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES,
-          Integer.toString(keyPropertyRefs.size() - referencedNames.size()), "1");
-    }
-
-    if (keys.size() < keyPropertyRefs.size() && partner != null) {
-      // Fill missing keys from referential constraints.
-      for (final String name : edmEntityType.getKeyPredicateNames()) {
-        boolean found = false;
-        for (final UriParameter key : keys) {
-          if (name.equals(key.getName())) {
-            found = true;
-            break;
-          }
-        }
-        if (!found && referencedNames.get(name) != null) {
-          keys.add(0, new UriParameterImpl().setName(name).setReferencedProperty(referencedNames.get(name)));
-        }
-      }
-    }
-
-    // Check that all key predicates are filled from the URI.
-    if (keys.size() < keyPropertyRefs.size()) {
-      throw new UriParserSemanticException(
-          "Expected " + keyPropertyRefs.size() + " key predicates but found " + keys.size() + ".",
-          UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES,
-          Integer.toString(keyPropertyRefs.size()), Integer.toString(keys.size()));
-    } else {
-      return keys;
-    }
-  }
-
-  private UriParameter simpleKey(final EdmKeyPropertyRef edmKeyPropertyRef)
-      throws UriParserException, UriValidationException {
-    final EdmProperty edmProperty = edmKeyPropertyRef == null ? null : edmKeyPropertyRef.getProperty();
-    if (nextPrimitiveTypeValue(
-        edmProperty == null ? null : (EdmPrimitiveType) edmProperty.getType(),
-        edmProperty == null ? false : edmProperty.isNullable())) {
-      final String literalValue = tokenizer.getText();
-      ParserHelper.requireNext(tokenizer, TokenKind.CLOSE);
-      return createUriParameter(edmProperty, edmKeyPropertyRef.getName(), literalValue);
-    } else {
-      throw new UriParserSemanticException("The key value is not valid.",
-          UriParserSemanticException.MessageKeys.INVALID_KEY_VALUE, edmKeyPropertyRef.getName());
-    }
-  }
-
-  private List<UriParameter> compoundKey(final EdmEntityType edmEntityType)
-      throws UriParserException, UriValidationException {
-
-    List<UriParameter> parameters = new ArrayList<UriParameter>();
-    List<String> parameterNames = new ArrayList<String>();
-
-    // To validate that each key predicate is exactly specified once, we use a list to pick from.
-    List<String> remainingKeyNames = new ArrayList<String>(edmEntityType.getKeyPredicateNames());
-
-    // At least one key predicate is mandatory.  Try to fetch all.
-    boolean hasComma = false;
-    do {
-      final String keyPredicateName = tokenizer.getText();
-      if (parameterNames.contains(keyPredicateName)) {
-        throw new UriValidationException("Duplicated key property " + keyPredicateName,
-            UriValidationException.MessageKeys.DOUBLE_KEY_PROPERTY, keyPredicateName);
-      }
-      if (remainingKeyNames.isEmpty()) {
-        throw new UriParserSemanticException("Too many key properties.",
-            UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES,
-            Integer.toString(parameters.size()), Integer.toString(parameters.size() + 1));
-      }
-      if (!remainingKeyNames.remove(keyPredicateName)) {
-        throw new UriValidationException("Unknown key property " + keyPredicateName,
-            UriValidationException.MessageKeys.INVALID_KEY_PROPERTY, keyPredicateName);
-      }
-      parameters.add(keyValuePair(keyPredicateName, edmEntityType));
-      parameterNames.add(keyPredicateName);
-      hasComma = tokenizer.next(TokenKind.COMMA);
-      if (hasComma) {
-        ParserHelper.requireNext(tokenizer, TokenKind.ODataIdentifier);
-      }
-    } while (hasComma);
-    ParserHelper.requireNext(tokenizer, TokenKind.CLOSE);
-
-    return parameters;
-  }
-
-  private UriParameter keyValuePair(final String keyPredicateName, final EdmEntityType edmEntityType)
-      throws UriParserException, UriValidationException {
-    final EdmKeyPropertyRef keyPropertyRef = edmEntityType.getKeyPropertyRef(keyPredicateName);
-    final EdmProperty edmProperty = keyPropertyRef == null ? null : keyPropertyRef.getProperty();
-    if (edmProperty == null) {
-      throw new UriValidationException(keyPredicateName + " is not a valid key property name.",
-          UriValidationException.MessageKeys.INVALID_KEY_PROPERTY, keyPredicateName);
-    }
-    ParserHelper.requireNext(tokenizer, TokenKind.EQ);
-    if (tokenizer.next(TokenKind.COMMA) || tokenizer.next(TokenKind.CLOSE) || tokenizer.next(TokenKind.EOF)) {
-      throw new UriParserSyntaxException("Key value expected.", UriParserSyntaxException.MessageKeys.SYNTAX);
-    }
-    if (nextPrimitiveTypeValue((EdmPrimitiveType) edmProperty.getType(), edmProperty.isNullable())) {
-      return createUriParameter(edmProperty, keyPredicateName, tokenizer.getText());
-    } else {
-      throw new UriParserSemanticException(keyPredicateName + " has not a valid  key value.",
-          UriParserSemanticException.MessageKeys.INVALID_KEY_VALUE, keyPredicateName);
-    }
-  }
-
-  private 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 EdmPrimitiveType primitiveType = (EdmPrimitiveType) edmProperty.getType();
-    try {
-      if (!(primitiveType.validate(primitiveType.fromUriLiteral(literalValue), 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",
-          UriValidationException.MessageKeys.INVALID_KEY_PROPERTY, parameterName);
-    }
-
-    return new UriParameterImpl()
-        .setName(parameterName)
-        .setText("null".equals(literalValue) ? null : literalValue);
-  }
-
   private UriResource typeCast(final FullQualifiedName name, final EdmStructuredType type,
       final UriResourcePartTyped previousTyped) throws UriParserException, UriValidationException {
     if (type.compatibleTo(previousTyped.getType())) {
@@ -501,7 +318,7 @@ public class ResourcePathParser {
         }
         if (tokenizer.next(TokenKind.OPEN)) {
           ((UriResourceWithKeysImpl) previousTyped).setKeyPredicates(
-              keyPredicate((EdmEntityType) type, null));
+              ParserHelper.parseKeyPredicate(tokenizer, (EdmEntityType) type, null));
         }
       } else {
         previousTypeFilter = ((UriResourceTypedImpl) previousTyped).getTypeFilter();
@@ -534,11 +351,8 @@ 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 = functionParameters();
-    List<String> names = new ArrayList<String>();
-    for (final UriParameter parameter : parameters) {
-      names.add(parameter.getName());
-    }
+    final List<UriParameter> parameters = ParserHelper.parseFunctionParameters(tokenizer, false);
+    final List<String> names = ParserHelper.getParameterNames(parameters);
     EdmFunction function = null;
     if (edmFunctionImport != null) {
       function = edmFunctionImport.getUnboundFunction(names);
@@ -557,16 +371,13 @@ public class ResourcePathParser {
             UriParserSemanticException.MessageKeys.UNKNOWN_PART, boundFunctionName.getFullQualifiedNameAsString());
       }
     }
-    UriResourceFunctionImpl resource = new UriResourceFunctionImpl()
-        .setFunctionImport(edmFunctionImport, null)
-        .setFunction(function)
-        .setParameters(parameters);
+    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(
-            keyPredicate((EdmEntityType) function.getReturnType().getType(), null));
+            ParserHelper.parseKeyPredicate(tokenizer, (EdmEntityType) function.getReturnType().getType(), null));
       } else {
         throw new UriParserSemanticException("A key is not allowed.",
             UriParserSemanticException.MessageKeys.KEY_NOT_ALLOWED);
@@ -575,106 +386,4 @@ public class ResourcePathParser {
     ParserHelper.requireTokenEnd(tokenizer);
     return resource;
   }
-
-  private List<UriParameter> functionParameters() throws UriParserException {
-    List<UriParameter> parameters = new ArrayList<UriParameter>();
-    ParserHelper.requireNext(tokenizer, TokenKind.OPEN);
-    if (tokenizer.next(TokenKind.CLOSE)) {
-      return parameters;
-    }
-    do {
-      ParserHelper.requireNext(tokenizer, TokenKind.ODataIdentifier);
-      final String name = tokenizer.getText();
-      if (parameters.contains(name)) {
-        throw new UriParserSemanticException("Duplicated function parameter " + name,
-            UriParserSemanticException.MessageKeys.INVALID_KEY_VALUE, name);
-      }
-      ParserHelper.requireNext(tokenizer, TokenKind.EQ);
-      if (tokenizer.next(TokenKind.COMMA) || tokenizer.next(TokenKind.CLOSE) || tokenizer.next(TokenKind.EOF)) {
-        throw new UriParserSyntaxException("Parameter value expected.", UriParserSyntaxException.MessageKeys.SYNTAX);
-      }
-      if (tokenizer.next(TokenKind.ParameterAliasName)) {
-        parameters.add(new UriParameterImpl().setName(name).setAlias(tokenizer.getText()));
-      } else if (nextPrimitiveValue()) {
-        final String literalValue = tokenizer.getText();
-        parameters.add(new UriParameterImpl().setName(name)
-            .setText("null".equals(literalValue) ? null : literalValue));
-      } else {
-        throw new UriParserSemanticException("Wrong parameter value.",
-            UriParserSemanticException.MessageKeys.INVALID_KEY_VALUE, "");
-      }
-    } while (tokenizer.next(TokenKind.COMMA));
-    ParserHelper.requireNext(tokenizer, TokenKind.CLOSE);
-    return parameters;
-  }
-
-  private boolean nextPrimitiveTypeValue(final EdmPrimitiveType primitiveType, final boolean nullable) {
-    final EdmPrimitiveType type = primitiveType instanceof EdmTypeDefinition ?
-        ((EdmTypeDefinition) primitiveType).getUnderlyingType() :
-        primitiveType;
-    if (tokenizer.next(TokenKind.ParameterAliasName)) {
-      return true;
-    } else if (nullable && tokenizer.next(TokenKind.NULL)) {
-      return true;
-
-    } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Boolean).equals(type)) {
-      return tokenizer.next(TokenKind.BooleanValue);
-    } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.String).equals(type)) {
-      return tokenizer.next(TokenKind.StringValue);
-    } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.SByte).equals(type)
-        || odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Byte).equals(type)
-        || odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Int16).equals(type)
-        || odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Int32).equals(type)
-        || odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Int64).equals(type)) {
-      return tokenizer.next(TokenKind.IntegerValue);
-    } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Guid).equals(type)) {
-      return tokenizer.next(TokenKind.GuidValue);
-    } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Date).equals(type)) {
-      return tokenizer.next(TokenKind.DateValue);
-    } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.DateTimeOffset).equals(type)) {
-      return tokenizer.next(TokenKind.DateTimeOffsetValue);
-    } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.TimeOfDay).equals(type)) {
-      return tokenizer.next(TokenKind.TimeOfDayValue);
-    } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Decimal).equals(type)) {
-      // The order is important.
-      // A decimal value should not be parsed as integer and let the tokenizer stop at the decimal point.
-      return tokenizer.next(TokenKind.DecimalValue)
-          || tokenizer.next(TokenKind.IntegerValue);
-    } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Double).equals(type)) {
-      // The order is important.
-      // A floating-point value should not be parsed as decimal and let the tokenizer stop at 'E'.
-      // A decimal value should not be parsed as integer and let the tokenizer stop at the decimal point.
-      return tokenizer.next(TokenKind.DoubleValue)
-          || tokenizer.next(TokenKind.DecimalValue)
-          || tokenizer.next(TokenKind.IntegerValue);
-    } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Duration).equals(type)) {
-      return tokenizer.next(TokenKind.DurationValue);
-    } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Binary).equals(type)) {
-      return tokenizer.next(TokenKind.BinaryValue);
-    } else if (type.getKind() == EdmTypeKind.ENUM) {
-      return tokenizer.next(TokenKind.EnumValue);
-    } else {
-      return false;
-    }
-  }
-
-  private boolean nextPrimitiveValue() {
-    return tokenizer.next(TokenKind.NULL)
-        || tokenizer.next(TokenKind.BooleanValue)
-        || tokenizer.next(TokenKind.StringValue)
-
-        // The order of the next seven expressions is important in order to avoid
-        // finding partly parsed tokens (counter-intuitive as it may be, even a GUID may start with digits ...).
-        || tokenizer.next(TokenKind.DoubleValue)
-        || tokenizer.next(TokenKind.DecimalValue)
-        || tokenizer.next(TokenKind.GuidValue)
-        || tokenizer.next(TokenKind.DateTimeOffsetValue)
-        || tokenizer.next(TokenKind.DateValue)
-        || tokenizer.next(TokenKind.TimeOfDayValue)
-        || tokenizer.next(TokenKind.IntegerValue)
-
-        || tokenizer.next(TokenKind.DurationValue)
-        || tokenizer.next(TokenKind.BinaryValue)
-        || tokenizer.next(TokenKind.EnumValue);
-  }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a8091658/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 b257e68..00f3673 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
@@ -156,10 +156,10 @@ public class SelectParser {
         throw new UriParserSemanticException("Function not found.",
             UriParserSemanticException.MessageKeys.UNKNOWN_PART, qualifiedName.getFullQualifiedNameAsString());
       } else {
-        return new UriResourceFunctionImpl().setFunction(boundFunction);
+        return new UriResourceFunctionImpl(null, boundFunction, null);
       }
     } else {
-      return new UriResourceActionImpl().setAction(boundAction);
+      return new UriResourceActionImpl(boundAction);
     }
   }
 
@@ -187,16 +187,16 @@ public class SelectParser {
             UriParserSemanticException.MessageKeys.EXPRESSION_PROPERTY_NOT_IN_TYPE,
             referencedType.getName(), name);
       } else {
-        resource.addResourcePart(new UriResourceNavigationPropertyImpl().setNavigationProperty(navigationProperty));
+        resource.addResourcePart(new UriResourceNavigationPropertyImpl(navigationProperty));
       }
 
     } else if (property.isPrimitive()
         || property.getType().getKind() == EdmTypeKind.ENUM
         || property.getType().getKind() == EdmTypeKind.DEFINITION) {
-      resource.addResourcePart(new UriResourcePrimitivePropertyImpl().setProperty(property));
+      resource.addResourcePart(new UriResourcePrimitivePropertyImpl(property));
 
     } else {
-      UriResourceComplexPropertyImpl complexPart = new UriResourceComplexPropertyImpl().setProperty(property);
+      UriResourceComplexPropertyImpl complexPart = new UriResourceComplexPropertyImpl(property);
       resource.addResourcePart(complexPart);
       if (tokenizer.next(TokenKind.SLASH)) {
         if (tokenizer.next(TokenKind.QualifiedName)) {

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a8091658/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriContext.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriContext.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriContext.java
index c0db85b..36a0887 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriContext.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriContext.java
@@ -32,10 +32,9 @@ import org.apache.olingo.server.core.uri.queryoption.SelectItemImpl;
  */
 public class UriContext {
 
-  public static class LambdaVariables {
+  public static class LambdaVariable {
     public String name;
     public EdmType type;
-    public boolean isCollection;
   }
 
   /**
@@ -43,7 +42,7 @@ public class UriContext {
    * As lambda functions can be nested there may be more than one allowed lambda variables at a time while parsing a
    * $filter or $orderby expressions.
    */
-  public Deque<LambdaVariables> allowedLambdaVariables;
+  public Deque<LambdaVariable> allowedLambdaVariables;
   /**
    * Used to stack type information for nested $expand, $filter query options and other cases.
    */
@@ -110,7 +109,7 @@ public class UriContext {
     contextReadingFunctionParameters = false;
     contextSelectItem = null;
     contextTypes = new ArrayDeque<EdmType>();
-    allowedLambdaVariables = new ArrayDeque<UriContext.LambdaVariables>();
+    allowedLambdaVariables = new ArrayDeque<UriContext.LambdaVariable>();
 
   }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a8091658/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParseTreeVisitor.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParseTreeVisitor.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParseTreeVisitor.java
index 9d29ab2..1bab218 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParseTreeVisitor.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParseTreeVisitor.java
@@ -252,8 +252,8 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
     return new FullQualifiedName(namespace, odi);
   }
 
-  private UriContext.LambdaVariables getLambdaVar(final String odi) {
-    for (UriContext.LambdaVariables item : context.allowedLambdaVariables) {
+  private UriContext.LambdaVariable getLambdaVar(final String odi) {
+    for (UriContext.LambdaVariable item : context.allowedLambdaVariables) {
       if (item.name.equals(odi)) {
         return item;
       }
@@ -292,7 +292,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
               || parts.get(0) instanceof UriResourceRoot)) {
         ensureNamespaceIsNull(ctx.vNS);
         context.contextUriInfo.addResourcePart(
-            new UriResourceEntitySetImpl().setEntitSet(edmEntitySet));
+            new UriResourceEntitySetImpl(edmEntitySet));
         return null;
       }
 
@@ -303,7 +303,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
               || parts.get(0) instanceof UriResourceRoot)) {
         ensureNamespaceIsNull(ctx.vNS);
         context.contextUriInfo.addResourcePart(
-            new UriResourceSingletonImpl().setSingleton(edmSingleton));
+            new UriResourceSingletonImpl(edmSingleton));
         return null;
       }
 
@@ -314,7 +314,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
               || parts.get(0) instanceof UriResourceRoot)) {
         ensureNamespaceIsNull(ctx.vNS);
         context.contextUriInfo.addResourcePart(
-            new UriResourceActionImpl().setActionImport(edmActionImport));
+            new UriResourceActionImpl(edmActionImport));
         return null;
       }
 
@@ -344,9 +344,6 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
         // mark parameters as consumed
         ctx.vlNVO.remove(0);
 
-        UriResourceFunctionImpl uriResource = new UriResourceFunctionImpl()
-            .setFunctionImport(edmFunctionImport, parameters);
-
         // collect parameter names
         List<String> names = new ArrayList<String>();
         for (UriParameter item : parameters) {
@@ -366,7 +363,9 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
         }
 
         ensureNamespaceIsNull(ctx.vNS);
-        uriResource.setFunction(edmFunctionImport.getUnboundFunction(names));
+        UriResourceFunctionImpl uriResource = new UriResourceFunctionImpl(edmFunctionImport,
+            edmFunctionImport.getUnboundFunction(names),
+            parameters);
         context.contextUriInfo.addResourcePart(uriResource);
         return null;
       }
@@ -390,7 +389,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
       sourceType = context.contextTypes.peek();
       sourceIsCollection = context.isCollection;
     } else if (lastResourcePart instanceof UriResourcePartTyped) {
-      sourceType = Parser.getTypeInformation((UriResourcePartTyped) lastResourcePart);
+      sourceType = ParserHelper.getTypeInformation((UriResourcePartTyped) lastResourcePart);
       sourceIsCollection = ((UriResourcePartTyped) lastResourcePart).isCollection();
     } else {
       throw wrap(new UriParserSemanticException(
@@ -401,12 +400,9 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
     if (ctx.vNS == null) { // without namespace
 
       // first check for lambda variable because a newly add property should not shadow a long used lambda variable
-      UriContext.LambdaVariables lVar = getLambdaVar(odi);
+      UriContext.LambdaVariable lVar = getLambdaVar(odi);
       if (lVar != null) {
-        UriResourceLambdaVarImpl lambdaResource = new UriResourceLambdaVarImpl();
-        lambdaResource.setVariableText(lVar.name);
-        lambdaResource.setType(lVar.type);
-        lambdaResource.setCollection(lVar.isCollection);
+        UriResourceLambdaVarImpl lambdaResource = new UriResourceLambdaVarImpl(lVar.name, lVar.type);
         context.contextUriInfo.addResourcePart(lambdaResource);
         return null;
       }
@@ -442,14 +438,13 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
             || property.getType().getKind() == EdmTypeKind.ENUM
             || property.getType().getKind() == EdmTypeKind.DEFINITION) {
           // create simple property
-          UriResourcePrimitivePropertyImpl simpleResource = new UriResourcePrimitivePropertyImpl()
-              .setProperty((EdmProperty) property);
+          UriResourcePrimitivePropertyImpl simpleResource =
+              new UriResourcePrimitivePropertyImpl((EdmProperty) property);
           context.contextUriInfo.addResourcePart(simpleResource);
           return null;
         } else {
           // create complex property
-          UriResourceComplexPropertyImpl complexResource = new UriResourceComplexPropertyImpl()
-              .setProperty((EdmProperty) property);
+          UriResourceComplexPropertyImpl complexResource = new UriResourceComplexPropertyImpl((EdmProperty) property);
           context.contextUriInfo.addResourcePart(complexResource);
           return null;
         }
@@ -461,8 +456,8 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
               UriParserSemanticException.MessageKeys.KEY_NOT_ALLOWED));
         }
 
-        UriResourceNavigationPropertyImpl navigationResource = new UriResourceNavigationPropertyImpl()
-            .setNavigationProperty((EdmNavigationProperty) property);
+        UriResourceNavigationPropertyImpl navigationResource =
+            new UriResourceNavigationPropertyImpl((EdmNavigationProperty) property);
         context.contextUriInfo.addResourcePart(navigationResource);
         return null;
       } else {
@@ -488,9 +483,9 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
 
           if (lastResourcePart == null) {
             // this may be the case if a member expression within a filter starts with a typeCast
-            UriResourceStartingTypeFilterImpl uriResource = new UriResourceStartingTypeFilterImpl()
-                .setType(filterEntityType)
-                .setCollection(sourceIsCollection);
+            UriResourceStartingTypeFilterImpl uriResource = new UriResourceStartingTypeFilterImpl(
+                filterEntityType,
+                sourceIsCollection);
             if (sourceIsCollection) {
               uriResource.setCollectionTypeFilter(filterEntityType);
             } else {
@@ -562,9 +557,8 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
           // is simple complex type cast
           if (lastResourcePart == null) {
             // this may be the case if a member expression within a filter starts with a typeCast
-            UriResourceStartingTypeFilterImpl uriResource = new UriResourceStartingTypeFilterImpl()
-                .setType(filterComplexType)
-                .setCollection(sourceIsCollection);
+            UriResourceStartingTypeFilterImpl uriResource =
+                new UriResourceStartingTypeFilterImpl(filterComplexType, sourceIsCollection);
 
             if (sourceIsCollection) {
               uriResource.setCollectionTypeFilter(filterComplexType);
@@ -626,8 +620,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
       // check for action
       EdmAction action = edm.getBoundAction(fullFilterName, fullBindingTypeName, sourceIsCollection);
       if (action != null) {
-        UriResourceActionImpl pathInfoAction = new UriResourceActionImpl();
-        pathInfoAction.setAction(action);
+        UriResourceActionImpl pathInfoAction = new UriResourceActionImpl(action);
         context.contextUriInfo.addResourcePart(pathInfoAction);
         return null;
       }
@@ -652,9 +645,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
       EdmFunction function = edm.getBoundFunction(fullFilterName, fullBindingTypeName, sourceIsCollection, names);
 
       if (function != null) {
-        UriResourceFunctionImpl pathInfoFunction = new UriResourceFunctionImpl()
-            .setFunction(function)
-            .setParameters(parameters);
+        UriResourceFunctionImpl pathInfoFunction = new UriResourceFunctionImpl(null, function, parameters);
         context.contextUriInfo.addResourcePart(pathInfoFunction);
 
         // mark parameters as consumed
@@ -666,9 +657,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
       function = edm.getUnboundFunction(fullFilterName, names);
 
       if (function != null) {
-        UriResourceFunctionImpl pathInfoFunction = new UriResourceFunctionImpl()
-            .setFunction(function)
-            .setParameters(parameters);
+        UriResourceFunctionImpl pathInfoFunction = new UriResourceFunctionImpl(null, function, parameters);
         context.contextUriInfo.addResourcePart(pathInfoFunction);
 
         // mark parameters as consumed
@@ -706,8 +695,6 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
 
   @Override
   public Object visitAllExpr(final AllExprContext ctx) {
-    UriResourceLambdaAllImpl all = new UriResourceLambdaAllImpl();
-
     UriResource obj = context.contextUriInfo.getLastResourcePart();
     if (!(obj instanceof UriResourcePartTyped)) {
       throw wrap(new UriParserSemanticException("all only allowed on typed path segments",
@@ -720,16 +707,14 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
       }
     }
 
-    UriContext.LambdaVariables var = new UriContext.LambdaVariables();
+    UriContext.LambdaVariable var = new UriContext.LambdaVariable();
     var.name = ctx.vLV.getText();
-    var.type = Parser.getTypeInformation((UriResourcePartTyped) obj);
-    var.isCollection = false;
+    var.type = ParserHelper.getTypeInformation((UriResourcePartTyped) obj);
 
-    all.setLamdaVariable(ctx.vLV.getText());
     context.allowedLambdaVariables.push(var);
-    all.setExpression((Expression) ctx.vLE.accept(this));
+    Expression expression = (Expression) ctx.vLE.accept(this);
     context.allowedLambdaVariables.pop();
-    return all;
+    return new UriResourceLambdaAllImpl(var.name, expression);
   }
 
   @Override
@@ -895,7 +880,6 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
 
   @Override
   public Object visitAnyExpr(final AnyExprContext ctx) {
-    UriResourceLambdaAnyImpl any = new UriResourceLambdaAnyImpl();
     if (ctx.vLV != null) {
       UriResourceImpl lastResourcePart = (UriResourceImpl) context.contextUriInfo.getLastResourcePart();
       if (!(lastResourcePart instanceof UriResourcePartTyped)) {
@@ -909,17 +893,16 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
         }
       }
 
-      UriContext.LambdaVariables var = new UriContext.LambdaVariables();
+      UriContext.LambdaVariable var = new UriContext.LambdaVariable();
       var.name = ctx.vLV.getText();
-      var.type = Parser.getTypeInformation((UriResourcePartTyped) lastResourcePart);
-      var.isCollection = false;
+      var.type = ParserHelper.getTypeInformation((UriResourcePartTyped) lastResourcePart);
 
-      any.setLamdaVariable(ctx.vLV.getText());
       context.allowedLambdaVariables.push(var);
-      any.setExpression((Expression) ctx.vLE.accept(this));
+      Expression expression = (Expression) ctx.vLE.accept(this);
       context.allowedLambdaVariables.pop();
+      return new UriResourceLambdaAnyImpl(var.name, expression);
     }
-    return any;
+    return null;
   }
 
   @Override
@@ -1238,18 +1221,18 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
     if (context.contextExpandItemPath == null) {
       // use the type of the last resource path segement
       UriResourceTypedImpl lastSegment = (UriResourceTypedImpl) context.contextUriInfo.getLastResourcePart();
-      targetType = Parser.getTypeInformation(lastSegment);
+      targetType = ParserHelper.getTypeInformation(lastSegment);
       isColl = lastSegment.isCollection();
     } else {
       if (context.contextExpandItemPath.getResourcePath() == null) {
         // use the type of the last resource path segement
         UriResourceTypedImpl lastSegment = (UriResourceTypedImpl) context.contextUriInfo.getLastResourcePart();
-        targetType = Parser.getTypeInformation(lastSegment);
+        targetType = ParserHelper.getTypeInformation(lastSegment);
         isColl = lastSegment.isCollection();
       } else {
         // use the type of the last ''expand'' path segement
         UriInfoImpl info = (UriInfoImpl) context.contextExpandItemPath.getResourcePath();
-        targetType = Parser.getTypeInformation((UriResourcePartTyped) info.getLastResourcePart());
+        targetType = ParserHelper.getTypeInformation((UriResourcePartTyped) info.getLastResourcePart());
         isColl = ((UriResourcePartTyped) info.getLastResourcePart()).isCollection();
       }
     }
@@ -1400,10 +1383,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
     }
 
     if (ctx.vIt != null || ctx.vIts != null) {
-      UriResourceItImpl pathInfoIT = new UriResourceItImpl();
-      pathInfoIT.setType(context.contextTypes.peek());
-      pathInfoIT.setCollection(context.isCollection);
-      uriInfoImplpath.addResourcePart(pathInfoIT);
+      uriInfoImplpath.addResourcePart(new UriResourceItImpl(context.contextTypes.peek(), context.isCollection));
     }
 
     if (ctx.vPs != null) {
@@ -1915,9 +1895,9 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
 
     UriResourcePartTyped lastType = (UriResourcePartTyped) lastResource;
 
-    UriResourceRootImpl pathInfoRoot = new UriResourceRootImpl();
-    pathInfoRoot.setCollection(lastType.isCollection());
-    pathInfoRoot.setType(Parser.getTypeInformation(lastType));
+    UriResourceRootImpl pathInfoRoot = new UriResourceRootImpl(
+        ParserHelper.getTypeInformation(lastType),
+        lastType.isCollection());
 
     UriInfoImpl uriInfoImplpath = new UriInfoImpl().setKind(UriInfoKind.resource);
     uriInfoImplpath.addResourcePart(pathInfoRoot);
@@ -2010,7 +1990,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
         UriInfoImpl uriInfo = (UriInfoImpl) context.contextSelectItem.getResourcePath();
         UriResource last = uriInfo.getLastResourcePart();
 
-        prevType = Parser.getTypeInformation((UriResourcePartTyped) last);
+        prevType = ParserHelper.getTypeInformation((UriResourcePartTyped) last);
         if (prevType == null) {
           throw wrap(new UriParserSemanticException("prev segment not typed",
               UriParserSemanticException.MessageKeys.ONLY_FOR_TYPED_PARTS, "select"));
@@ -2038,8 +2018,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
             || property.getType().getKind() == EdmTypeKind.ENUM
             || property.getType().getKind() == EdmTypeKind.DEFINITION) {
 
-          UriResourcePrimitivePropertyImpl simple = new UriResourcePrimitivePropertyImpl();
-          simple.setProperty(property);
+          UriResourcePrimitivePropertyImpl simple = new UriResourcePrimitivePropertyImpl(property);
 
           UriInfoImpl uriInfo = (UriInfoImpl) context.contextSelectItem.getResourcePath();
           if (uriInfo == null) {
@@ -2059,8 +2038,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
         } else {
           UriInfoImpl uriInfo = (UriInfoImpl) context.contextSelectItem.getResourcePath();
 
-          UriResourceComplexPropertyImpl complex = new UriResourceComplexPropertyImpl();
-          complex.setProperty(property);
+          UriResourceComplexPropertyImpl complex = new UriResourceComplexPropertyImpl(property);
 
           if (uriInfo == null) {
             uriInfo = new UriInfoImpl().setKind(UriInfoKind.resource);
@@ -2096,7 +2074,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
           EdmComplexType ct = edm.getComplexType(fullName);
           if (ct != null) {
             if ((ct.compatibleTo(prevType))) {
-              UriResourceStartingTypeFilterImpl resourcePart = new UriResourceStartingTypeFilterImpl();
+              UriResourceStartingTypeFilterImpl resourcePart = new UriResourceStartingTypeFilterImpl(null, false);
               resourcePart.setCollectionTypeFilter(ct);
 
               UriInfoImpl uriInfo = new UriInfoImpl().setKind(UriInfoKind.resource);
@@ -2115,7 +2093,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
           EdmEntityType et = edm.getEntityType(fullName);
           if (et != null) {
             if ((et.compatibleTo(prevType))) {
-              UriResourceStartingTypeFilterImpl resourcePart = new UriResourceStartingTypeFilterImpl();
+              UriResourceStartingTypeFilterImpl resourcePart = new UriResourceStartingTypeFilterImpl(null, false);
               resourcePart.setCollectionTypeFilter(et);
 
               UriInfoImpl uriInfo = new UriInfoImpl().setKind(UriInfoKind.resource);
@@ -2142,13 +2120,13 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
           throw wrap(new UriParserSemanticException("prev segment typed",
               UriParserSemanticException.MessageKeys.ONLY_FOR_TYPED_PARTS, "select"));
         }
-        EdmType prevType = Parser.getTypeInformation((UriResourcePartTyped) last);
+        EdmType prevType = ParserHelper.getTypeInformation((UriResourcePartTyped) last);
 
         if (prevType instanceof EdmComplexType) {
           EdmComplexType ct = edm.getComplexType(fullName);
           if (ct != null) {
             if ((ct.compatibleTo(prevType))) {
-              UriResourceStartingTypeFilterImpl resourcePart = new UriResourceStartingTypeFilterImpl();
+              UriResourceStartingTypeFilterImpl resourcePart = new UriResourceStartingTypeFilterImpl(null, false);
               resourcePart.setCollectionTypeFilter(ct);
 
               uriInfo.addResourcePart(resourcePart);
@@ -2186,7 +2164,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
           throw wrap(new UriParserSemanticException("prev segment typed",
               UriParserSemanticException.MessageKeys.PREVIOUS_PART_TYPED));
         }
-        prevType = Parser.getTypeInformation((UriResourcePartTyped) last);
+        prevType = ParserHelper.getTypeInformation((UriResourcePartTyped) last);
       }
 
       final FullQualifiedName finalTypeName = prevType.getFullQualifiedName();
@@ -2195,8 +2173,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
       EdmAction action = edm.getBoundAction(fullName, finalTypeName, null);
 
       if (action != null) {
-        UriResourceActionImpl uriAction = new UriResourceActionImpl();
-        uriAction.setAction(action);
+        UriResourceActionImpl uriAction = new UriResourceActionImpl(action);
 
         UriInfoImpl resourcePath = (UriInfoImpl) context.contextSelectItem.getResourcePath();
         resourcePath.addResourcePart(uriAction);
@@ -2206,8 +2183,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
       EdmFunction function = edm.getBoundFunction(fullName, finalTypeName, null, null);
 
       if (function != null) {
-        UriResourceFunctionImpl uriFunction = new UriResourceFunctionImpl();
-        uriFunction.setFunction(function);
+        UriResourceFunctionImpl uriFunction = new UriResourceFunctionImpl(null, function, null);
 
         UriInfoImpl resourcePath = (UriInfoImpl) context.contextSelectItem.getResourcePath();
         resourcePath.addResourcePart(uriFunction);

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a8091658/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 4b43cd9..37f1b76 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
@@ -40,10 +40,14 @@ public class UriTokenizer {
     ROOT,
     IT,
 
+    ANY,
+    ALL,
+
     OPEN,
     CLOSE,
     COMMA,
     SEMI,
+    COLON,
     DOT,
     SLASH,
     EQ,
@@ -119,7 +123,10 @@ public class UriTokenizer {
     TotalsecondsMethod,
     ToupperMethod,
     TrimMethod,
-    YearMethod
+    YearMethod,
+
+    AscSuffix,
+    DescSuffix
   }
 
   private final String parseString;
@@ -174,6 +181,13 @@ public class UriTokenizer {
       found = nextConstant("$it");
       break;
 
+    case ANY:
+      found = nextConstant("any");
+      break;
+    case ALL:
+      found = nextConstant("all");
+      break;
+
     case OPEN:
       found = nextCharacter('(');
       break;
@@ -186,6 +200,9 @@ public class UriTokenizer {
     case SEMI:
       found = nextCharacter(';');
       break;
+    case COLON:
+      found = nextCharacter(':');
+      break;
     case DOT:
       found = nextCharacter('.');
       break;
@@ -409,6 +426,14 @@ public class UriTokenizer {
     case YearMethod:
       found = nextMethod("year");
       break;
+
+    // Suffixes
+    case AscSuffix:
+      found = nextSuffix("asc");
+      break;
+    case DescSuffix:
+      found = nextSuffix("desc");
+      break;
     }
 
     if (found) {
@@ -543,6 +568,15 @@ public class UriTokenizer {
   }
 
   /**
+   * Moves past (required) whitespace and the given suffix name if found;
+   * otherwise leaves the index unchanged.
+   * @return whether the suffix has been found at the current index
+   */
+  private boolean nextSuffix(final String suffixName) {
+    return nextWhitespace() && nextConstant(suffixName);
+  }
+
+  /**
    * Moves past an OData identifier if found; otherwise leaves the index unchanged.
    * @return whether an OData identifier has been found at the current index
    */

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a8091658/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/MemberImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/MemberImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/MemberImpl.java
index a71e382..6ef37e4 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/MemberImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/MemberImpl.java
@@ -94,4 +94,9 @@ public class MemberImpl implements Member {
     }
     return false;
   }
+
+  @Override
+  public String toString() {
+    return path.getUriResourceParts().toString() + (startTypeFilter == null ? "" : startTypeFilter);
+  }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a8091658/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 4c76e96..68e6637 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
@@ -25,6 +25,7 @@ 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;
 import org.apache.olingo.server.api.uri.UriInfo;
@@ -33,9 +34,6 @@ import org.apache.olingo.server.api.uri.UriResourceAction;
 import org.apache.olingo.server.api.uri.UriResourceEntitySet;
 import org.apache.olingo.server.api.uri.queryoption.AliasQueryOption;
 import org.apache.olingo.server.api.uri.queryoption.QueryOption;
-import org.apache.olingo.server.core.uri.UriInfoImpl;
-import org.apache.olingo.server.core.uri.UriResourceActionImpl;
-import org.apache.olingo.server.core.uri.UriResourceEntitySetImpl;
 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.CustomQueryOptionImpl;
@@ -86,9 +84,9 @@ public class UriInfoImplTest {
   public void resourceParts() {
     UriInfoImpl uriInfo = new UriInfoImpl();
 
-    final UriResourceAction action = new UriResourceActionImpl();
-    final UriResourceEntitySet entitySet0 = new UriResourceEntitySetImpl();
-    final UriResourceEntitySet entitySet1 = new UriResourceEntitySetImpl();
+    final UriResourceAction action = new UriResourceActionImpl((EdmAction) null);
+    final UriResourceEntitySet entitySet0 = new UriResourceEntitySetImpl(null);
+    final UriResourceEntitySet entitySet1 = new UriResourceEntitySetImpl(null);
 
     uriInfo.addResourcePart(action);
     uriInfo.addResourcePart(entitySet0);

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a8091658/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 183ff22..4ab7fce 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
@@ -28,6 +28,7 @@ import java.util.Locale;
 import org.apache.olingo.server.api.OData;
 import org.apache.olingo.server.api.uri.queryoption.expression.Expression;
 import org.apache.olingo.server.core.uri.parser.UriTokenizer.TokenKind;
+import org.apache.olingo.server.core.uri.validator.UriValidationException;
 import org.junit.Test;
 
 public class ExpressionParserTest {
@@ -127,7 +128,7 @@ public class ExpressionParserTest {
   @Test
   public void unary() throws Exception {
     Expression expression = parseExpression("-5");
-    assertEquals("{MINUS 5}", expression.toString());
+    assertEquals("-5", expression.toString());
 
     assertEquals("{MINUS -1}", parseExpression("--1").toString());
     assertEquals("{MINUS duration'PT1M'}", parseExpression("-duration'PT1M'").toString());
@@ -135,13 +136,13 @@ public class ExpressionParserTest {
     expression = parseExpression("not false");
     assertEquals("{NOT false}", expression.toString());
 
-    wrongExpression("-11:12:13");
+    wrongExpression("not 11:12:13");
   }
 
   @Test
   public void grouping() throws Exception {
     Expression expression = parseExpression("-5 add 5");
-    assertEquals("{{MINUS 5} ADD 5}", expression.toString());
+    assertEquals("{-5 ADD 5}", expression.toString());
 
     expression = parseExpression("-(5 add 5)");
     assertEquals("{MINUS {5 ADD 5}}", expression.toString());
@@ -149,7 +150,7 @@ public class ExpressionParserTest {
 
   @Test
   public void precedence() throws Exception {
-    assertEquals("{{MINUS 1} ADD {2 DIV 3}}", parseExpression("-1 add 2 div 3").toString());
+    assertEquals("{-1 ADD {2 DIV 3}}", parseExpression("-1 add 2 div 3").toString());
     assertEquals("{true OR {{NOT false} AND true}}", parseExpression("true or not false and true").toString());
   }
 
@@ -264,7 +265,8 @@ public class ExpressionParserTest {
     wrongExpression("substring(1,2)");
   }
 
-  private Expression parseMethod(TokenKind kind, String... parameters) throws UriParserException {
+  private Expression parseMethod(TokenKind kind, String... parameters)
+      throws UriParserException, UriValidationException {
     String expressionString = kind.name().substring(0, kind.name().indexOf("Method"))
         .toLowerCase(Locale.ROOT).replace("geo", "geo.") + '(';
     boolean first = true;
@@ -283,9 +285,10 @@ public class ExpressionParserTest {
     return expression;
   }
 
-  private Expression parseExpression(final String expressionString) throws UriParserException {
+  private Expression parseExpression(final String expressionString)
+      throws UriParserException, UriValidationException {
     UriTokenizer tokenizer = new UriTokenizer(expressionString);
-    Expression expression = new ExpressionParser(null, odata).parse(tokenizer);
+    Expression expression = new ExpressionParser(null, odata).parse(tokenizer, null, null);
     assertNotNull(expression);
     assertTrue(tokenizer.next(TokenKind.EOF));
     return expression;
@@ -293,10 +296,12 @@ public class ExpressionParserTest {
 
   private void wrongExpression(final String expressionString) {
     try {
-      new ExpressionParser(null, odata).parse(new UriTokenizer(expressionString));
+      new ExpressionParser(null, odata).parse(new UriTokenizer(expressionString), null, null);
       fail("Expected exception not thrown.");
     } catch (final UriParserException e) {
       assertNotNull(e);
+    } catch (final UriValidationException e) {
+      assertNotNull(e);
     }
   }
 }


Mime
View raw message