You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by ko...@apache.org on 2014/01/29 13:45:36 UTC

[4/6] [OLINGO-63] Uri Parser: Add test cases for key predicates, select, expand and code cleanup

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/blob/1ef03f92/odata4-lib/odata4-producer-core/src/main/java/org/apache/olingo/odata4/producer/core/uri/UriParseTreeVisitor.java
----------------------------------------------------------------------
diff --git a/odata4-lib/odata4-producer-core/src/main/java/org/apache/olingo/odata4/producer/core/uri/UriParseTreeVisitor.java b/odata4-lib/odata4-producer-core/src/main/java/org/apache/olingo/odata4/producer/core/uri/UriParseTreeVisitor.java
index 2ae5675..4e07ae4 100644
--- a/odata4-lib/odata4-producer-core/src/main/java/org/apache/olingo/odata4/producer/core/uri/UriParseTreeVisitor.java
+++ b/odata4-lib/odata4-producer-core/src/main/java/org/apache/olingo/odata4/producer/core/uri/UriParseTreeVisitor.java
@@ -46,115 +46,17 @@ import org.apache.olingo.odata4.commons.api.edm.provider.FullQualifiedName;
 import org.apache.olingo.odata4.producer.api.uri.UriInfoKind;
 import org.apache.olingo.odata4.producer.api.uri.UriResourcePart;
 import org.apache.olingo.odata4.producer.api.uri.UriResourcePartTyped;
+import org.apache.olingo.odata4.producer.api.uri.queryoption.SelectItem;
 import org.apache.olingo.odata4.producer.api.uri.queryoption.expression.SupportedBinaryOperators;
 import org.apache.olingo.odata4.producer.api.uri.queryoption.expression.SupportedMethodCalls;
 import org.apache.olingo.odata4.producer.core.uri.antlr.UriLexer;
 import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserBaseVisitor;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.AliasAndValueContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.AllExprContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.AltAddContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.AltAllContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.AltAndContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.AltAnyContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.AltBatchContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.AltComparismContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.AltEntityCastContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.AltEntityContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.AltEqualityContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.AltLiteralContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.AltMetadataContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.AltMultContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.AltOrContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.AltResourcePathContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.AnyExprContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.CastExprContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.CeilingMethodCallExprContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.ConcatMethodCallExprContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.ConstSegmentContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.ContainsMethodCallExprContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.CrossjoinContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.CustomQueryOptionContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.DayMethodCallExprContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.DistanceMethodCallExprContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.EndsWithMethodCallExprContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.EntityOptionCastContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.EntityOptionContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.EntityOptionsCastContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.EntityOptionsContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.ExpandContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.ExpandCountOptionContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.ExpandItemContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.ExpandOptionContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.ExpandPathContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.ExpandPathExtensionContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.ExpandPathSegmentContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.ExpandRefOptionContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.FilterContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.FloorMethodCallExprContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.FormatContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.FractionalsecondsMethodCallExprContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.GeoLengthMethodCallExprContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.HourMethodCallExprContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.IdContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.IndexOfMethodCallExprContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.InlinecountContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.IntersectsMethodCallExprContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.IsofExprContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.LengthMethodCallExprContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.MaxDateTimeMethodCallExprContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.MemberExprContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.MinDateTimeMethodCallExprContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.MinuteMethodCallExprContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.MonthMethodCallExprContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.NameValueOptListContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.NameValuePairContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.NamespaceContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.NowMethodCallExprContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.OdataIdentifierContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.OdataRelativeUriEOFContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.OrderByContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.PathSegmentContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.PathSegmentsContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.QueryOptionContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.QueryOptionsContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.ResourcePathContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.RootExprContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.RoundMethodCallExprContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.SecondMethodCallExprContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.SelectContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.SelectItemContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.SelectSegmentContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.StartsWithMethodCallExprContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.SubstringMethodCallExprContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.TimeMethodCallExprContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.ToLowerMethodCallExprContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.ToUpperMethodCallExprContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.TotalOffsetMinutesMethodCallExprContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.TotalsecondsMethodCallExprContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.TrimMethodCallExprContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.UnaryContext;
-import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.YearMethodCallExprContext;
-import org.apache.olingo.odata4.producer.core.uri.queryoption.AliasQueryOptionImpl;
-import org.apache.olingo.odata4.producer.core.uri.queryoption.CustomQueryOptionImpl;
-import org.apache.olingo.odata4.producer.core.uri.queryoption.ExpandItemImpl;
-import org.apache.olingo.odata4.producer.core.uri.queryoption.ExpandOptionImpl;
-import org.apache.olingo.odata4.producer.core.uri.queryoption.ExpandSegment;
-import org.apache.olingo.odata4.producer.core.uri.queryoption.FilterOptionImpl;
-import org.apache.olingo.odata4.producer.core.uri.queryoption.FormatOptionImpl;
-import org.apache.olingo.odata4.producer.core.uri.queryoption.IdOptionImpl;
-import org.apache.olingo.odata4.producer.core.uri.queryoption.LevelOptionImpl;
-import org.apache.olingo.odata4.producer.core.uri.queryoption.OrderByOptionImpl;
-import org.apache.olingo.odata4.producer.core.uri.queryoption.QueryOptionImpl;
-import org.apache.olingo.odata4.producer.core.uri.queryoption.SelectItemOptionImpl;
-import org.apache.olingo.odata4.producer.core.uri.queryoption.SelectOptionImpl;
-import org.apache.olingo.odata4.producer.core.uri.queryoption.SystemQueryOptionImpl;
-import org.apache.olingo.odata4.producer.core.uri.queryoption.expression.BinaryImpl;
-import org.apache.olingo.odata4.producer.core.uri.queryoption.expression.ExpressionImpl;
-import org.apache.olingo.odata4.producer.core.uri.queryoption.expression.LambdaRefImpl;
-import org.apache.olingo.odata4.producer.core.uri.queryoption.expression.LiteralImpl;
-import org.apache.olingo.odata4.producer.core.uri.queryoption.expression.MemberImpl;
-import org.apache.olingo.odata4.producer.core.uri.queryoption.expression.MethodCallImpl;
-import org.apache.olingo.odata4.producer.core.uri.queryoption.expression.TypeLiteralImpl;
+import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.SkipContext;
+import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.SkiptokenContext;
+import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.TopContext;
+import org.apache.olingo.odata4.producer.core.uri.antlr.UriParserParser.*;
+import org.apache.olingo.odata4.producer.core.uri.queryoption.*;
+import org.apache.olingo.odata4.producer.core.uri.queryoption.expression.*;
 
 /**
  * UriVisitor
@@ -173,21 +75,20 @@ import org.apache.olingo.odata4.producer.core.uri.queryoption.expression.TypeLit
  * - Parsing the context of $metadata
  */
 public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
-
   private Edm edm;
-  private EdmEntityContainer edmEntityContainer;
 
-  // --- context ---
-  private SelectItemOptionImpl contextSelectItem;
-  private UriInfoImpl contextUriInfo;
+  private EdmEntityContainer edmEntityContainer;
 
   /**
-   * Set within method {@link #visitExpandPath(ExpandPathContext ctx)} to allow nodes
-   * deeper in the parse tree appending path segments to the currently processed {@link ExpandItemImpl}.
-   * <li>The context is required because the following path segments depend on the successor.</li>
-   * <li>A stack is used because the $expand system query option can be nested.</li>
+   * Hold all currently allowed lambda variables
+   * As lambda functions can be nested there may be more than one allowed lambda variables while parsing a
+   * $filter or $orderby expression.
    */
-  private Stack<ExpandItemImpl> contextExpandItemPath = new Stack<ExpandItemImpl>();
+  private class LambdaVariables {
+    public boolean isCollection;
+    public String name;
+    public EdmType type;
+  }
 
   /**
    * Set to allow nodes deeper in the parse tree appending path segments to the currently
@@ -196,91 +97,165 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
    * <li>A stack is used because some system query options which are applied to the last type can
    * be nested ($expand, $filter)</li>
    */
-  private Stack<EdmType> contextType = new Stack<EdmType>();
-  private Stack<String> lambdaVariables = new Stack<String>();
-  private LambdaRefImpl contextDetectedLambda;
+  private class LastTypeColl {
+    private boolean isCollection;
+    private EdmType type;
+
+    LastTypeColl(EdmType type, boolean isCollection) {
+      this.type = type;
+      this.isCollection = isCollection;
+    }
+  }
+
+  // --- context ---
+
+  private Stack<LambdaVariables> allowedLambdaVariables = new Stack<LambdaVariables>();
+
+  /**
+   * Set within method {@link #visitExpandItem(ExpandPathContext ctx)} and {@link #visitExpandPathExtension(final
+   * ExpandPathExtensionContext ctx)} to allow nodes
+   * deeper in the expand tree at {@link #visitExpandPathExtension(ExpandPathExtensionContext ctx)} appending path
+   * segments to the currently processed {@link ExpandItemImpl}.
+   */
+  private ExpandItemImpl contextExpandItemPath;
+
+  /**
+   * Set within method {@link #visitSelectItem(SelectItemContext ctx)} to allow nodes
+   * deeper in the expand tree at {@link #visitSelectSegment(SelectSegmentContext ctx)} appending path segments to the
+   * currently processed {@link SelectItemOptionImpl}.
+   */
+  private SelectItemOptionImpl contextSelectItem;
+
+  private Stack<LastTypeColl> contextTypes = new Stack<LastTypeColl>();
+
+  /**
+   * Stores the currently processed UriInfo objects. There is one URI Info object for the resource path
+   * and one for each new first member access within $filter and $orderBy options.
+   */
+  private UriInfoImpl contextUriInfo;
+
+  // --- class ---
 
-  public UriParseTreeVisitor(Edm edm) {
+  public UriParseTreeVisitor(final Edm edm) {
     this.edm = edm;
-    this.edmEntityContainer = edm.getEntityContainer(null);
+    edmEntityContainer = edm.getEntityContainer(null);
   }
 
-  public UriResourceImplTyped readFirstPathInfoSegment(PathSegmentContext ctx) {
-    UriInfoImpl uriInfoResource = this.contextUriInfo;
+  private FullQualifiedName getFullName(final NamespaceContext vNS, final String odi) {
+    if (vNS != null) {
+      String namespace = vNS.getText();
+      namespace = namespace.substring(0, namespace.length() - 1);
+
+      return new FullQualifiedName(namespace, odi);
+    }
+    return null;
+
+  }
+
+  /* here */
+  private LambdaVariables getLambdaVar(String odi) {
+    for (LambdaVariables item : this.allowedLambdaVariables) {
+      if (item.name.equals(odi)) {
+        return item;
+      }
+    }
+    return null;
+  }
 
+  private EdmType getLastType(final UriResourceImplTyped lastResourceSegment) {
+    if (lastResourceSegment instanceof UriResourceImplKeyPred) {
+      UriResourceImplKeyPred lastKeyPred = (UriResourceImplKeyPred) lastResourceSegment;
+      if (lastKeyPred.getTypeFilterOnEntry() != null) {
+        return lastKeyPred.getTypeFilterOnEntry();
+      } else if (lastKeyPred.getTypeFilterOnCollection() != null) {
+        return lastKeyPred.getTypeFilterOnCollection();
+      }
+    }
+    EdmType type = lastResourceSegment.getTypeFilter();
+    if (type != null) {
+      return type;
+    }
+
+    return lastResourceSegment.getType();
+  }
+
+  public UriResourceImplTyped readFirstPathInfoSegment(final PathSegmentContext ctx) {
     String odi = ctx.vODI.getText();
 
     // check EntitySet
-    EdmEntitySet edmES = edmEntityContainer.getEntitySet(odi);
-    if (edmES != null) {
-      UriResourceEntitySetImpl uriPathInfo = new UriResourceEntitySetImpl();
-      uriPathInfo.setEntitSet(edmES);
-      uriInfoResource.addPathInfo(uriPathInfo);
+    EdmEntitySet edmEntitySet = edmEntityContainer.getEntitySet(odi);
+    if (edmEntitySet != null) {
+      UriResourceEntitySetImpl uriResource = new UriResourceEntitySetImpl();
+      uriResource.setEntitSet(edmEntitySet);
+      contextUriInfo.addPathInfo(uriResource);
       return null;
     }
 
     // check Singleton
-    EdmSingleton edmSI = edmEntityContainer.getSingleton(odi);
-    if (edmSI != null) {
-      UriResourceSingletonImpl uriPathInfo = new UriResourceSingletonImpl();
-      uriPathInfo.setSingleton(edmSI);
-      uriInfoResource.addPathInfo(uriPathInfo);
+    EdmSingleton edmSingleton = edmEntityContainer.getSingleton(odi);
+    if (edmSingleton != null) {
+      UriResourceSingletonImpl uriResource = new UriResourceSingletonImpl();
+      uriResource.setSingleton(edmSingleton);
+      contextUriInfo.addPathInfo(uriResource);
       return null;
     }
 
     // check ActionImport
-    EdmActionImport edmAI = edmEntityContainer.getActionImport(odi);
-    if (edmAI != null) {
-      UriResourceActionImpl uriPathInfo = new UriResourceActionImpl();
-      uriPathInfo.setActionImport(edmAI);
-      
-      uriInfoResource.addPathInfo(uriPathInfo);
+    EdmActionImport edmActionImport = edmEntityContainer.getActionImport(odi);
+    if (edmActionImport != null) {
+      UriResourceActionImpl uriResource = new UriResourceActionImpl();
+      uriResource.setActionImport(edmActionImport);
+      contextUriInfo.addPathInfo(uriResource);
       return null;
     }
 
     // check FunctionImport
-    EdmFunctionImport edmFI = edmEntityContainer.getFunctionImport(odi);
-    if (edmFI != null) {
+    EdmFunctionImport edmFunctionImport = edmEntityContainer.getFunctionImport(odi);
+    if (edmFunctionImport != null) {
 
       // read the URI parameters
       List<UriParameterImpl> parameters = (List<UriParameterImpl>) ctx.vlNVO.get(0).accept(this);
       ctx.vlNVO.remove(0); // parameters are consumed
 
-      UriResourceFunctionImpl uriPathInfo = new UriResourceFunctionImpl();
-      uriPathInfo.setFunctionImport(edmFI, parameters);
-      uriInfoResource.addPathInfo(uriPathInfo);
+      UriResourceFunctionImpl uriResource = new UriResourceFunctionImpl();
+      uriResource.setFunctionImport(edmFunctionImport, parameters);
+      contextUriInfo.addPathInfo(uriResource);
       return null;
     }
 
-    throw wrap(new UriParserSemanticException("Unkown path segment found: " + odi));
+    throw wrap(new UriParserSemanticException("Unkown path segment: " + odi));
   }
 
-  public UriResourceImplTyped readNextPathInfoSegment(PathSegmentContext ctx) {
+  public UriResourceImplTyped readNextPathInfoSegment(final PathSegmentContext ctx) {
     String odi = ctx.vODI.getText();
 
-    if (!(this.contextUriInfo.getLastUriPathInfo() instanceof UriResourceImplTyped)) {
+    UriResourcePart lastResource = contextUriInfo.getLastResourcePart();
+    if (!(lastResource instanceof UriResourceImplTyped)) {
       throw wrap(new UriParserSemanticException("Previous path segment not typed"));
     }
 
-    UriResourceImplTyped lastSegment = (UriResourceImplTyped) this.contextUriInfo.getLastUriPathInfo();
-    // TODO add check for type filters
+    UriResourceImplTyped lastTyped = (UriResourceImplTyped) lastResource;
 
-    if (ctx.vNS == null) {
+    if (ctx.vNS == null) { // without namespace
 
-      //first check for lamda variable because a newly add property should not shaddow a long used lamdavarable
-      
-      if (this.lambdaVariables.contains(odi)) {
-        contextDetectedLambda = new LambdaRefImpl().setVariableText(odi);
+      // first check for lambda variable because a newly add property should not shadow a long used lambda variable
+      LambdaVariables lVar = getLambdaVar(odi);
+      if (lVar != null) {
+        UriResourceLambdaRefImpl lambdaResource = new UriResourceLambdaRefImpl();
+        lambdaResource.setVariableText(lVar.name);
+        lambdaResource.setType(lVar.type);
+        lambdaResource.isCollection(lVar.isCollection);
+        contextUriInfo.addPathInfo(lambdaResource);
         return null;
       }
-      
-      //
-      EdmType targetType = getLastType(lastSegment);
+
+      EdmType targetType = getLastType(lastTyped);
       if (!(targetType instanceof EdmStructuralType)) {
-        throw wrap(new UriParserSemanticException("Property " + odi + " not found"));
+        throw wrap(new UriParserSemanticException("Previous path segment not a structural type"));
       }
 
       EdmStructuralType structType = (EdmStructuralType) targetType;
+
       EdmElement property = structType.getProperty(odi);
       if (property == null) {
         throw wrap(new UriParserSemanticException("Unkown property: " + odi));
@@ -288,100 +263,109 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
 
       if (property instanceof EdmProperty) {
         if (((EdmProperty) property).isPrimitive() == true) {
-          UriResourceSimplePropertyImpl uriPropertyImpl = new UriResourceSimplePropertyImpl();
-          uriPropertyImpl.setProperty((EdmProperty) property);
-          this.contextUriInfo.addPathInfo(uriPropertyImpl);
+          // create simple property
+          UriResourceSimplePropertyImpl simpleResource = new UriResourceSimplePropertyImpl();
+          simpleResource.setProperty((EdmProperty) property);
+          contextUriInfo.addPathInfo(simpleResource);
           return null;
         } else {
-          UriResourceComplexPropertyImpl uriPropertyImpl = new UriResourceComplexPropertyImpl();
-          uriPropertyImpl.setProperty((EdmProperty) property);
-          this.contextUriInfo.addPathInfo(uriPropertyImpl);
+          // create complex property
+          UriResourceComplexPropertyImpl complexResource = new UriResourceComplexPropertyImpl();
+          complexResource.setProperty((EdmProperty) property);
+          contextUriInfo.addPathInfo(complexResource);
           return null;
         }
       } else if (property instanceof EdmNavigationProperty) {
-        UriResourceNavigationPropertyImpl uriPathInfoNavigation = new UriResourceNavigationPropertyImpl();
-        uriPathInfoNavigation.addNavigationProperty((EdmNavigationProperty) property);
-        contextUriInfo.addPathInfo(uriPathInfoNavigation);
+        // create navigation property
+        UriResourceNavigationPropertyImpl navigationResource = new UriResourceNavigationPropertyImpl();
+        navigationResource.setNavigationProperty((EdmNavigationProperty) property);
+        contextUriInfo.addPathInfo(navigationResource);
         return null;
       } else {
         throw wrap(new UriParserSemanticException("Unkown property type"));
       }
 
-    } else {
-      FullQualifiedName fullName = getFullName(ctx.vNS, odi);
-      EdmType lastType = getLastType(lastSegment);
+    } else { // with namespace
+
+      FullQualifiedName fullFilterName = getFullName(ctx.vNS, odi);
+
+      EdmType lastType = getLastType(lastTyped);
 
       if (lastType instanceof EdmEntityType) {
 
-        EdmEntityType et = edm.getEntityType(fullName);
-        if (et != null) {
-          // is simple entity type cast
-          if (!(et.compatibleTo(lastType))) {
-            throw wrap(new UriParserSemanticException("Types not kompatible"));
+        EdmEntityType filterEntityType = edm.getEntityType(fullFilterName);
+        if (filterEntityType != null) {
+
+          // is entity type cast
+          if (!(filterEntityType.compatibleTo(lastType))) {
+            throw wrap(new UriParserSemanticException(
+                "Entity typefilter not compatible to previous path segment: " + fullFilterName.toString()));
           }
 
-          // check if last segement may contain key properties
-          if (lastSegment instanceof UriResourceImplKeyPred) {
-            UriResourceImplKeyPred lastKeyPred = (UriResourceImplKeyPred) lastSegment;
+          // check if last segment may contain key properties
+          if (lastTyped instanceof UriResourceImplKeyPred) {
+            UriResourceImplKeyPred lastKeyPred = (UriResourceImplKeyPred) lastTyped;
 
             if (lastKeyPred.isCollection() == false) {
               if (lastKeyPred.getTypeFilterOnEntry() != null) {
-                throw wrap(new UriParserSemanticException("Single typeFilter are not chainable"));
+                throw wrap(new UriParserSemanticException("Single type filters are not chainable"));
               }
-              lastKeyPred.setSingleTypeFilter(et);
+              lastKeyPred.setSingleTypeFilter(filterEntityType);
               return null;
             } else {
               if (lastKeyPred.getTypeFilterOnCollection() != null) {
-                throw wrap(new UriParserSemanticException("Collection typeFilters are not chainable"));
+                throw wrap(new UriParserSemanticException("Collection type filters are not chainable"));
               }
-              lastKeyPred.setCollectionTypeFilter(et);
+              lastKeyPred.setCollectionTypeFilter(filterEntityType);
               return null;
             }
-
           } else {
-            // is
-            if (lastSegment.getTypeFilter() != null) {
-              throw wrap(new UriParserSemanticException("Chaining typefilters not allowed"));
+            if (lastTyped.getTypeFilter() != null) {
+              throw wrap(new UriParserSemanticException("type filters are not chainable"));
             }
 
-            lastSegment.setTypeFilter(et);
+            lastTyped.setTypeFilter(filterEntityType);
             return null;
           }
-
         }
+
       } else if (lastType instanceof EdmComplexType) {
-        EdmComplexType ct = edm.getComplexType(fullName);
-        if (ct != null) {
-          if (!(ct.compatibleTo(lastType))) {
 
-            throw wrap(new UriParserSemanticException("Types not kompatible"));
+        EdmComplexType filterComplexType = edm.getComplexType(fullFilterName);
+
+        if (filterComplexType != null) {
+
+          // is complex type cast
+          if (!(filterComplexType.compatibleTo(lastType))) {
+            throw wrap(new UriParserSemanticException(
+                "Complex typefilter not compatible to previous path segment: " + fullFilterName.toString()));
           }
 
           // is simple complex type cast
-          if (lastSegment instanceof UriResourceImplKeyPred) {
-            UriResourceImplKeyPred lastKeyPred = (UriResourceImplKeyPred) lastSegment;
+          if (lastTyped instanceof UriResourceImplKeyPred) {
+            // e.g. in case of function returning complex data or a list of complex data
+            UriResourceImplKeyPred lastKeyPred = (UriResourceImplKeyPred) lastTyped;
 
             if (lastKeyPred.isCollection() == false) {
               if (lastKeyPred.getTypeFilterOnEntry() != null) {
                 throw wrap(new UriParserSemanticException("Single TypeFilter are not chainable"));
               }
-              lastKeyPred.setSingleTypeFilter(ct);
+              lastKeyPred.setSingleTypeFilter(filterComplexType);
               return null;
             } else {
               if (lastKeyPred.getTypeFilterOnCollection() != null) {
                 throw wrap(new UriParserSemanticException("Collection TypeFilter are not chainable"));
               }
-              lastKeyPred.setCollectionTypeFilter(ct);
+              lastKeyPred.setCollectionTypeFilter(filterComplexType);
               return null;
             }
 
           } else {
-
-            if (lastSegment.getTypeFilter() != null) {
+            if (lastTyped.getTypeFilter() != null) {
               throw wrap(new UriParserSemanticException("Chaining Typefilters not allowed"));
             }
 
-            lastSegment.setTypeFilter(ct);
+            lastTyped.setTypeFilter(filterComplexType);
             return null;
           }
         }
@@ -390,15 +374,14 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
       FullQualifiedName fullBindingTypeName = new FullQualifiedName(lastType.getNamespace(), lastType.getName());
 
       // check for action
-      EdmAction action = edm.getAction(fullName, fullBindingTypeName, lastSegment.isCollection());
+      EdmAction action = edm.getAction(fullFilterName, fullBindingTypeName, lastTyped.isCollection());
       if (action != null) {
         UriResourceActionImpl pathInfoAction = new UriResourceActionImpl();
         pathInfoAction.setAction(action);
-        this.contextUriInfo.addPathInfo(pathInfoAction);
+        contextUriInfo.addPathInfo(pathInfoAction);
         return null;
       }
 
-      // path segemend is not a complex type and not a entity type
       // do a check for bound functions (which requires the parameter list)
 
       if (ctx.vlNVO.size() == 0) {
@@ -407,81 +390,75 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
 
       List<UriParameterImpl> parameters = (List<UriParameterImpl>) ctx.vlNVO.get(0).accept(this);
 
-      // handle bound function
-
       // get names of function parameters
       List<String> names = new ArrayList<String>();
       for (UriParameterImpl item : parameters) {
         names.add(item.getName());
       }
 
-      EdmFunction function =
-          edm.getFunction(fullName, fullBindingTypeName, lastSegment.isCollection(), names);
+      EdmFunction function = edm.getFunction(fullFilterName, fullBindingTypeName, lastTyped.isCollection(), names);
 
       if (function != null) {
         UriResourceFunctionImpl pathInfoFunction = new UriResourceFunctionImpl();
         pathInfoFunction.setFunction(function);
         pathInfoFunction.setParameters(parameters);
-        this.contextUriInfo.addPathInfo(pathInfoFunction);
-        ctx.vlNVO.remove(0);// as the parameters are consumed
+        contextUriInfo.addPathInfo(pathInfoFunction);
+        ctx.vlNVO.remove(0);// parameters are consumed
         return null;
       }
 
-      // check for special case
-      if (lastSegment instanceof UriResourceItImpl) {
-        if (((UriResourceItImpl) lastSegment).isExplicitIt() == false) {
+      // check for unbound function in the $filter case ( where the previous resource segment is a $it)
+      if (lastTyped instanceof UriResourceItImpl) {
+        if (((UriResourceItImpl) lastTyped).isExplicitIt() == false) {
           // check for unbound function
-          EdmFunction functionUnbound =
-              edm.getFunction(fullName, null, lastSegment.isCollection(), names);
+          EdmFunction functionUnbound = edm.getFunction(fullFilterName, null, lastTyped.isCollection(), names);
           if (functionUnbound != null) {
-            this.contextUriInfo.clearPathInfo(); // replace the $it
+            contextUriInfo.clearPathInfo(); // replace the $it
+
             // TODO maybe add $root pathinfo first
             UriResourceFunctionImpl pathInfoFunction = new UriResourceFunctionImpl();
             pathInfoFunction.setFunction(functionUnbound);
             pathInfoFunction.setParameters(parameters);
-            this.contextUriInfo.addPathInfo(pathInfoFunction);
-            ctx.vlNVO.remove(0);// as the parameters are consumed
+            contextUriInfo.addPathInfo(pathInfoFunction);
+            ctx.vlNVO.remove(0);// parameters are consumed
             return null;
           }
         }
       }
-      throw wrap(new UriParserSemanticException("Unknown resource path segment:" + fullName.toString()));
+      throw wrap(new UriParserSemanticException("Unknown resource path segment:" + fullFilterName.toString()));
 
     }
-
-  }
-
-  private EdmType getLastType(UriResourceImplTyped lastSegment) {
-    if (lastSegment instanceof UriResourceImplKeyPred) {
-      UriResourceImplKeyPred lastKeyPred = (UriResourceImplKeyPred) lastSegment;
-      if (lastKeyPred.getTypeFilterOnEntry() != null) {
-        return lastKeyPred.getTypeFilterOnEntry();
-      } else if (lastKeyPred.getTypeFilterOnCollection() != null) {
-        return lastKeyPred.getTypeFilterOnCollection();
-      }
-    }
-    EdmType type = lastSegment.getTypeFilter();
-    if (type != null) {
-      return type;
-    }
-
-    return lastSegment.getType();
   }
 
   @Override
-  public Object visitAliasAndValue(AliasAndValueContext ctx) {
-
+  public Object visitAliasAndValue(final AliasAndValueContext ctx) {
     AliasQueryOptionImpl alias = new AliasQueryOptionImpl();
-
     alias.setName(ctx.vODI.getText());
     alias.setText(ctx.vV.getText());
     alias.setAliasValue((ExpressionImpl) ctx.vV.accept(this));
-
     return alias;
   }
 
   @Override
-  public ExpressionImpl visitAltAdd(AltAddContext ctx) {
+  public Object visitAllExpr(final AllExprContext ctx) {
+    UriResourceAllImpl all = new UriResourceAllImpl();
+
+    LastTypeColl lastTypeInfo = this.contextTypes.peek();
+
+    LambdaVariables var = new LambdaVariables();
+    var.name = ctx.vLV.getText();
+    var.type = lastTypeInfo.type;
+    var.isCollection = lastTypeInfo.isCollection;
+
+    all.setLamdaVariable(ctx.vLV.getText());
+    allowedLambdaVariables.push(var);
+    all.setExpression((ExpressionImpl) ctx.vLE.accept(this));
+    allowedLambdaVariables.pop();
+    return all;
+  }
+
+  @Override
+  public ExpressionImpl visitAltAdd(final AltAddContext ctx) {
     BinaryImpl binary = new BinaryImpl();
 
     int tokenIndex = ctx.vO.getType();
@@ -498,7 +475,23 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
   }
 
   @Override
-  public ExpressionImpl visitAltAnd(AltAndContext ctx) {
+  public Object visitAltAll(final AltAllContext ctx) {
+    UriInfoImpl uriInfoImplpath = new UriInfoImpl().setKind(UriInfoKind.resource);
+
+    UriResourceItImpl pathInfoIT = new UriResourceItImpl();
+    LastTypeColl lastTypeInfo = this.contextTypes.peek();
+    pathInfoIT.setType(lastTypeInfo.type);
+    pathInfoIT.setCollection(lastTypeInfo.isCollection);
+
+    uriInfoImplpath.addPathInfo(pathInfoIT);
+    uriInfoImplpath.addPathInfo((UriResourcePartImpl) super.visitAltAll(ctx));
+
+    return new MemberImpl()
+        .setPath(uriInfoImplpath);
+  }
+
+  @Override
+  public ExpressionImpl visitAltAnd(final AltAndContext ctx) {
     BinaryImpl binary = new BinaryImpl();
 
     binary.setOperator(SupportedBinaryOperators.AND);
@@ -508,13 +501,28 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
   }
 
   @Override
-  public Object visitAltBatch(AltBatchContext ctx) {
-    this.contextUriInfo = new UriInfoImpl(edm).setKind(UriInfoKind.batch);
+  public Object visitAltAny(final AltAnyContext ctx) {
+    UriInfoImpl uriInfoImplpath = new UriInfoImpl().setKind(UriInfoKind.resource);
+
+    UriResourceItImpl pathInfoIT = new UriResourceItImpl();
+    pathInfoIT.setType(contextTypes.peek().type);
+    pathInfoIT.setCollection(contextTypes.peek().isCollection);
+
+    uriInfoImplpath.addPathInfo(pathInfoIT);
+    uriInfoImplpath.addPathInfo((UriResourcePartImpl) super.visitAltAny(ctx));
+
+    return new MemberImpl()
+        .setPath(uriInfoImplpath);
+  }
+
+  @Override
+  public Object visitAltBatch(final AltBatchContext ctx) {
+    contextUriInfo = new UriInfoImpl().setKind(UriInfoKind.batch);
     return null;
   }
 
   @Override
-  public ExpressionImpl visitAltComparism(AltComparismContext ctx) {
+  public ExpressionImpl visitAltComparism(final AltComparismContext ctx) {
     BinaryImpl binary = new BinaryImpl();
 
     int tokenIndex = ctx.vO.getType();
@@ -537,19 +545,19 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
   }
 
   @Override
-  public Object visitAltEntity(AltEntityContext ctx) {
-    UriInfoImpl uriInfo = new UriInfoImpl(edm).setKind(UriInfoKind.entityId);
+  public Object visitAltEntity(final AltEntityContext ctx) {
+    UriInfoImpl uriInfo = new UriInfoImpl().setKind(UriInfoKind.entityId);
 
     List<QueryOptionImpl> list = (List<QueryOptionImpl>) ctx.vEO.accept(this);
     uriInfo.setQueryOptions(list);
 
-    this.contextUriInfo = uriInfo;
+    contextUriInfo = uriInfo;
     return null;
   }
 
   @Override
-  public Object visitAltEntityCast(AltEntityCastContext ctx) {
-    UriInfoImpl uriInfo = new UriInfoImpl(edm).setKind(UriInfoKind.entityId);
+  public Object visitAltEntityCast(final AltEntityCastContext ctx) {
+    UriInfoImpl uriInfo = new UriInfoImpl().setKind(UriInfoKind.entityId);
 
     String odi = ctx.vODI.getText();
     FullQualifiedName fullName = getFullName(ctx.vNS, odi);
@@ -559,9 +567,9 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
       throw wrap(new UriParserSemanticException("Expected EntityTypeName"));
     }
     uriInfo.setEntityTypeCast(type);
-    
+
     contextUriInfo = uriInfo;
-    contextType.push(uriInfo.getEntityTypeCast());
+    contextTypes.push(new LastTypeColl(uriInfo.getEntityTypeCast(), true));
 
     List<QueryOptionImpl> list = (List<QueryOptionImpl>) ctx.vEO.accept(this);
     uriInfo.setQueryOptions(list);
@@ -569,12 +577,8 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
     return null;
   }
 
-  private ParseCancellationException wrap(UriParserException uriParserException) {
-    return new ParseCancellationException(uriParserException);
-  }
-
   @Override
-  public ExpressionImpl visitAltEquality(AltEqualityContext ctx) {
+  public ExpressionImpl visitAltEquality(final AltEqualityContext ctx) {
     BinaryImpl binary = new BinaryImpl();
 
     int tokenIndex = ctx.vO.getType();
@@ -591,13 +595,13 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
   }
 
   @Override
-  public Object visitAltLiteral(AltLiteralContext ctx) {
+  public Object visitAltLiteral(final AltLiteralContext ctx) {
     return new LiteralImpl().setText(ctx.getText());
   }
 
   @Override
-  public Object visitAltMetadata(AltMetadataContext ctx) {
-    UriInfoImpl uriInfo = new UriInfoImpl(edm).setKind(UriInfoKind.metadata);
+  public Object visitAltMetadata(final AltMetadataContext ctx) {
+    UriInfoImpl uriInfo = new UriInfoImpl().setKind(UriInfoKind.metadata);
 
     if (ctx.vF != null) {
       FormatOptionImpl format = (FormatOptionImpl) ctx.vF.accept(this);
@@ -608,12 +612,12 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
       throw wrap(new UriParserException("Fragment for $metadata not supported"));
     }
 
-    this.contextUriInfo = uriInfo;
+    contextUriInfo = uriInfo;
     return null;
   }
 
   @Override
-  public ExpressionImpl visitAltMult(AltMultContext ctx) {
+  public ExpressionImpl visitAltMult(final AltMultContext ctx) {
     BinaryImpl binary = new BinaryImpl();
 
     int tokenIndex = ctx.vO.getType();
@@ -632,7 +636,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
   }
 
   @Override
-  public ExpressionImpl visitAltOr(AltOrContext ctx) {
+  public ExpressionImpl visitAltOr(final AltOrContext ctx) {
     BinaryImpl binary = new BinaryImpl();
 
     binary.setOperator(SupportedBinaryOperators.OR);
@@ -643,14 +647,15 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
   }
 
   @Override
-  public Object visitAltResourcePath(AltResourcePathContext ctx) {
+  public Object visitAltResourcePath(final AltResourcePathContext ctx) {
     ctx.vRP.accept(this);
 
     if (ctx.vQO != null) {
-      UriResourcePart lastSegment = contextUriInfo.getLastUriPathInfo();
+      UriResourcePart lastSegment = contextUriInfo.getLastResourcePart();
 
       if (lastSegment instanceof UriResourceImplTyped) {
-        contextType.push(getLastType((UriResourceImplTyped) lastSegment));
+        UriResourceImplTyped typed = (UriResourceImplTyped) lastSegment;
+        contextTypes.push(new LastTypeColl(getLastType(typed), typed.isCollection()));
       }
       contextUriInfo.setQueryOptions((List<QueryOptionImpl>) ctx.vQO.accept(this));
     }
@@ -658,9 +663,29 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
   }
 
   @Override
-  public ExpressionImpl visitCastExpr(CastExprContext ctx) {
+  public Object visitAnyExpr(final AnyExprContext ctx) {
+    UriResourceAnyImpl any = new UriResourceAnyImpl();
+    if (ctx.vLV != null) {
+      LastTypeColl lastTypeInfo = this.contextTypes.peek();
+
+      LambdaVariables var = new LambdaVariables();
+      var.name = ctx.vLV.getText();
+      var.type = lastTypeInfo.type;
+      var.isCollection = lastTypeInfo.isCollection;
+
+      any.setLamdaVariable(ctx.vLV.getText());
+      allowedLambdaVariables.push(var);
+      any.setExpression((ExpressionImpl) ctx.vLE.accept(this));
+      allowedLambdaVariables.pop();
+    }
+    return any;
+  }
+
+  @Override
+  public ExpressionImpl visitCastExpr(final CastExprContext ctx) {
     MethodCallImpl method = new MethodCallImpl();
     if (ctx.vE1 != null) {
+      // is optional parameter
       ExpressionImpl onExpression = (ExpressionImpl) ctx.vE1.accept(this);
       method.addParameter(onExpression);
     }
@@ -674,14 +699,14 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
   }
 
   @Override
-  public ExpressionImpl visitCeilingMethodCallExpr(CeilingMethodCallExprContext ctx) {
+  public ExpressionImpl visitCeilingMethodCallExpr(final CeilingMethodCallExprContext ctx) {
     return new MethodCallImpl()
         .setMethod(SupportedMethodCalls.CEILING)
         .addParameter((ExpressionImpl) ctx.vE1.accept(this));
   }
 
   @Override
-  public ExpressionImpl visitConcatMethodCallExpr(ConcatMethodCallExprContext ctx) {
+  public ExpressionImpl visitConcatMethodCallExpr(final ConcatMethodCallExprContext ctx) {
     return new MethodCallImpl()
         .setMethod(SupportedMethodCalls.CONCAT)
         .addParameter((ExpressionImpl) ctx.vE1.accept(this))
@@ -689,7 +714,54 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
   }
 
   @Override
-  public ExpressionImpl visitContainsMethodCallExpr(ContainsMethodCallExprContext ctx) {
+  public Object visitConstSegment(final ConstSegmentContext ctx) {
+    UriInfoImpl uriInfoResource = contextUriInfo;
+    UriResourcePart pathInfo = uriInfoResource.getLastResourcePart();
+
+    if (ctx.vV != null) {
+      if (pathInfo instanceof UriResourcePartTyped) {
+        if (!((UriResourcePartTyped) pathInfo).isCollection()) {
+          contextUriInfo.addPathInfo(new UriResourceValueImpl());
+        } else {
+          throw wrap(new UriParserSemanticException("$value only allowed on typed path segments"));
+        }
+        return null;
+      } else {
+        throw wrap(new UriParserSemanticException("$value only allowed on typed path segments"));
+      }
+
+    } else if (ctx.vC != null) {
+      if (pathInfo instanceof UriResourceImplTyped) {
+        if (((UriResourceImplTyped) pathInfo).isCollection()) {
+          contextUriInfo.addPathInfo(new UriResourceCountImpl());
+        } else {
+          throw wrap(new UriParserSemanticException("$count only allowed on collection properties"));
+        }
+      } else {
+        throw wrap(new UriParserSemanticException("$count only allowed on typed properties"));
+      }
+    } else if (ctx.vR != null) {
+      if (pathInfo instanceof UriResourceImplTyped) {
+        EdmType type = ((UriResourceImplTyped) pathInfo).getType();
+        if (type instanceof EdmEntityType) {
+          contextUriInfo.addPathInfo(new UriResourceRefImpl());
+        } else {
+          throw wrap(new UriParserSemanticException("$ref only allowd on endity types"));
+        }
+      } else {
+        throw wrap(new UriParserSemanticException("$ref only allowed on typed properties"));
+      }
+
+    } else if (ctx.vAll != null) {
+      contextUriInfo.addPathInfo((UriResourceAllImpl) ctx.vAll.accept(this));
+    } else if (ctx.vAny != null) {
+      contextUriInfo.addPathInfo((UriResourceAnyImpl) ctx.vAny.accept(this));
+    }
+    return null;
+  }
+
+  @Override
+  public ExpressionImpl visitContainsMethodCallExpr(final ContainsMethodCallExprContext ctx) {
     return new MethodCallImpl()
         .setMethod(SupportedMethodCalls.CONTAINS)
         .addParameter((ExpressionImpl) ctx.vE1.accept(this))
@@ -697,19 +769,19 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
   }
 
   @Override
-  public Object visitCrossjoin(CrossjoinContext ctx) {
-    UriInfoImpl crossJoin = new UriInfoImpl(edm).setKind(UriInfoKind.crossjoin);
+  public Object visitCrossjoin(final CrossjoinContext ctx) {
+    UriInfoImpl crossJoin = new UriInfoImpl().setKind(UriInfoKind.crossjoin);
 
     for (OdataIdentifierContext obj : ctx.vlODI) {
       crossJoin.addEntitySetName(obj.getText());
     }
 
-    this.contextUriInfo = crossJoin;
+    contextUriInfo = crossJoin;
     return null;
   }
 
   @Override
-  public Object visitCustomQueryOption(CustomQueryOptionContext ctx) {
+  public Object visitCustomQueryOption(final CustomQueryOptionContext ctx) {
     CustomQueryOptionImpl queryOption = new CustomQueryOptionImpl();
     queryOption.setName(ctx.getChild(0).getText());
 
@@ -722,14 +794,14 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
   }
 
   @Override
-  public ExpressionImpl visitDayMethodCallExpr(DayMethodCallExprContext ctx) {
+  public ExpressionImpl visitDayMethodCallExpr(final DayMethodCallExprContext ctx) {
     return new MethodCallImpl()
         .setMethod(SupportedMethodCalls.DAY)
         .addParameter((ExpressionImpl) ctx.vE1.accept(this));
   }
 
   @Override
-  public ExpressionImpl visitDistanceMethodCallExpr(DistanceMethodCallExprContext ctx) {
+  public ExpressionImpl visitDistanceMethodCallExpr(final DistanceMethodCallExprContext ctx) {
     return new MethodCallImpl()
         .setMethod(SupportedMethodCalls.DISTANCE)
         .addParameter((ExpressionImpl) ctx.vE1.accept(this))
@@ -737,14 +809,14 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
   }
 
   @Override
-  public Object visitEndsWithMethodCallExpr(EndsWithMethodCallExprContext ctx) {
+  public Object visitEndsWithMethodCallExpr(final EndsWithMethodCallExprContext ctx) {
     return new MethodCallImpl()
         .setMethod(SupportedMethodCalls.ENDSWITH)
         .addParameter((ExpressionImpl) ctx.vE1.accept(this));
   }
 
   @Override
-  public Object visitEntityOptions(EntityOptionsContext ctx) {
+  public Object visitEntityOptions(final EntityOptionsContext ctx) {
     List<QueryOptionImpl> queryOptionList = new ArrayList<QueryOptionImpl>();
 
     for (EntityOptionContext entityOption : ctx.vlEOb) {
@@ -760,7 +832,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
   }
 
   @Override
-  public Object visitEntityOptionsCast(EntityOptionsCastContext ctx) {
+  public Object visitEntityOptionsCast(final EntityOptionsCastContext ctx) {
     List<QueryOptionImpl> queryOptionList = new ArrayList<QueryOptionImpl>();
     for (EntityOptionCastContext entityOption : ctx.vlEOb) {
       queryOptionList.add((QueryOptionImpl) entityOption.accept(this));
@@ -775,7 +847,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
   }
 
   @Override
-  public Object visitExpand(ExpandContext ctx) {
+  public Object visitExpand(final ExpandContext ctx) {
     ExpandOptionImpl expand = new ExpandOptionImpl();
     for (ExpandItemContext eI : ctx.vlEI) {
       expand.addExpandItem((ExpandItemImpl) eI.accept(this));
@@ -785,33 +857,32 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
   }
 
   @Override
-  public Object visitExpandItem(ExpandItemContext ctx) {
+  public Object visitExpandItem(final ExpandItemContext ctx) {
 
     ExpandItemImpl expandItem = null;
     if (ctx.vS != null) {
-      expandItem = new ExpandItemImpl().setStar(true);
+      expandItem = new ExpandItemImpl().setIsStar(true);
       if (ctx.vR != null) {
-        //expandItem.setRef(true);
-        //TODO do creat reference segement
+        expandItem.setIsRef(true);
       } else if (ctx.vM != null) {
-        expandItem.setExpandQueryOption(new LevelOptionImpl().setMax());
+        expandItem.setExpandQueryOption(new LevelExpandOptionImpl().setMax().setText(ctx.vM.getText()));
       } else if (ctx.vL != null) {
-        expandItem.setExpandQueryOption(new LevelOptionImpl().setValue(ctx.vL.getText()));
+        expandItem.setExpandQueryOption(new LevelExpandOptionImpl().setText(ctx.vL.getText()));
       }
 
     } else if (ctx.vEP != null) {
       expandItem = (ExpandItemImpl) ctx.vEP.accept(this);
-    } else {
-      // error
-    }
 
-    if (ctx.vEPE != null) {
-      contextExpandItemPath.push(expandItem);
-      List<SystemQueryOptionImpl> list = (List<SystemQueryOptionImpl>) ctx.vEPE.accept(this);
-      for (SystemQueryOptionImpl option : list) {
-        expandItem.setExpandQueryOption(option);
+      if (ctx.vEPE != null) {
+        ExpandItemImpl contextExpandItemPathBU = contextExpandItemPath;
+        contextExpandItemPath = expandItem;
+
+        List<SystemQueryOptionImpl> list = (List<SystemQueryOptionImpl>) ctx.vEPE.accept(this);
+        for (SystemQueryOptionImpl option : list) {
+          expandItem.setExpandQueryOption(option);
+        }
+        contextExpandItemPath = contextExpandItemPathBU;
       }
-      contextExpandItemPath.pop();
     }
 
     return expandItem;
@@ -819,134 +890,71 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
   }
 
   @Override
-  public Object visitExpandPath(ExpandPathContext ctx) {
+  public Object visitExpandPath(final ExpandPathContext ctx) {
     ExpandItemImpl expandItem = new ExpandItemImpl();
 
-    contextExpandItemPath.push(expandItem);
-
-    super.visitExpandPath(ctx);
-
-    contextExpandItemPath.pop();
-
-    return expandItem;
-  }
-
-  @Override
-  public Object visitExpandPathSegment(ExpandPathSegmentContext ctx) {
-    ExpandItemImpl expandItemPrev = contextExpandItemPath.peek();
-
-    String odi = ctx.vODI.getText();
-    if (ctx.vNS == null) {
-      EdmType targetType = null;
-      if (expandItemPrev.getLastSegement() == null) {
-        // used the global type
-        UriResourceImplTyped lastSegment = (UriResourceImplTyped) this.contextUriInfo.getLastUriPathInfo();
-        targetType = this.getLastType(lastSegment);
-      } else {
-        ExpandSegment segment = expandItemPrev.getLastSegement();
-        if (segment.getTypeFilter() != null) {
-          targetType = segment.getTypeFilter();
-        } else {
-          targetType = segment.getType();
-        }
-      }
-
-      if (!(targetType instanceof EdmStructuralType)) {
-        throw wrap(new UriParserSemanticException("Prev Expandsegment has no properties"));
-      }
-
-      EdmStructuralType structType = (EdmStructuralType) targetType;
-      EdmElement property = (EdmElement) structType.getProperty(odi);
-      if (property != null) {
-        ExpandSegment seg = new ExpandSegment();
-        seg.setProperty(property);
-        expandItemPrev.addSegment(seg);
-        return null;
-      }
-
-      throw wrap(new UriParserSemanticException("Prev Expandsegment has no property:" + odi));
+    UriResourceItImpl pathInfoIT = new UriResourceItImpl();
 
-    } else {
-      EdmType targetType = null;
-      if (expandItemPrev.getLastSegement() == null) {
-        UriResourceImplTyped lastSegment = (UriResourceImplTyped) this.contextUriInfo.getLastUriPathInfo();
-        targetType = this.getLastType(lastSegment);
+    UriResourceImplTyped tmp = (UriResourceImplTyped) contextUriInfo.getLastResourcePart();
+    pathInfoIT.setCollection(tmp.isCollection()).setType(getLastType(tmp));
 
-        ExpandSegment seg = new ExpandSegmentIt();
-        expandItemPrev.addSegment(seg);
+    // save context
+    ExpandItemImpl contextExpandItemPathBU = contextExpandItemPath;
+    UriInfoImpl uriInfoResourceBU = contextUriInfo;
 
-      } else {
-        ExpandSegment segment = expandItemPrev.getLastSegement();
-        if (segment.getTypeFilter() != null) {
-          throw wrap(new UriParserSemanticException("Prev Expandsegment has already a type filter"));
-        } else {
-          targetType = segment.getType();
-        }
-      }
+    // set tmp context
+    contextExpandItemPath = expandItem;
+    contextUriInfo = new UriInfoImpl().setKind(UriInfoKind.resource);
+    contextUriInfo.addPathInfo(pathInfoIT);
 
-      FullQualifiedName fullName = getFullName(ctx.vNS, odi);
+    super.visitExpandPath(ctx);
+    expandItem.setResourcePath(contextUriInfo);
 
-      if (targetType instanceof EdmEntityType) {
-        EdmEntityType et = edm.getEntityType(fullName);
-        if (et == null) {
-          throw wrap(new UriParserSemanticException("entity type not found"));
-        }
-        if (et.compatibleTo(targetType)) {
-          expandItemPrev.getLastSegement().setFilter(et);
-          return null;
-        }
-      }
+    // reset context
+    contextUriInfo = uriInfoResourceBU;
+    contextExpandItemPath = contextExpandItemPathBU;
 
-      if (targetType instanceof EdmComplexType) {
-        EdmComplexType ct = edm.getComplexType(fullName);
-        if (ct == null) {
-          throw wrap(new UriParserSemanticException("Complex type not found"));
-        }
-        if (ct.compatibleTo(targetType)) {
-          expandItemPrev.getLastSegement().setFilter(ct);
-          return null;
-        }
-      }
-    }
-    return null;
+    return expandItem;
   }
 
   @Override
-  public Object visitExpandPathExtension(ExpandPathExtensionContext ctx) {
-    ExpandItemImpl expandItemPrev = contextExpandItemPath.peek();
-
-    if (contextType == null) {
-      contextType = new Stack<EdmType>();
-    }
-
+  public Object visitExpandPathExtension(final ExpandPathExtensionContext ctx) {
     List<SystemQueryOptionImpl> list = new ArrayList<SystemQueryOptionImpl>();
 
     EdmType targetType = null;
-    if (expandItemPrev.getLastSegement() == null) {
-      // used the global type
-      UriResourceImplTyped lastSegment = (UriResourceImplTyped) this.contextUriInfo.getLastUriPathInfo();
-      targetType = this.getLastType(lastSegment);
+    boolean isColl = false;
+    if (contextExpandItemPath == null) {
+      // use the type of the last resource path segement
+      UriResourceImplTyped lastSegment = (UriResourceImplTyped) contextUriInfo.getLastResourcePart();
+      targetType = getLastType(lastSegment);
+      isColl = lastSegment.isCollection();
     } else {
-      ExpandSegment segment = expandItemPrev.getLastSegement();
-      if (segment.getTypeFilter() != null) {
-        targetType = segment.getTypeFilter();
+      if (contextExpandItemPath.getPath() == null) {
+        // use the type of the last resource path segement
+        UriResourceImplTyped lastSegment = (UriResourceImplTyped) contextUriInfo.getLastResourcePart();
+        targetType = getLastType(lastSegment);
+        isColl = lastSegment.isCollection();
       } else {
-        targetType = segment.getType();
+        // use the type of the last ''expand'' path segement
+        UriInfoImpl info = (UriInfoImpl) contextExpandItemPath.getPath();
+        targetType = getLastType((UriResourceImplTyped) info.getLastResourcePart());
+        isColl = ((UriResourceImplTyped) info.getLastResourcePart()).isCollection();
       }
     }
 
-    contextType.push(targetType);
+    contextTypes.push(new LastTypeColl(targetType, isColl));
 
     if (ctx.vC != null) {
-      ExpandSegment seg = new ExpandSegmentCount();
-      expandItemPrev.addSegment(seg);
+      UriInfoImpl resourcePath = (UriInfoImpl) contextExpandItemPath.getPath();
+      resourcePath.addPathInfo(new UriResourceCountImpl());
+
       for (ExpandCountOptionContext s : ctx.vlEOC) {
         list.add((SystemQueryOptionImpl) s.accept(this));
       }
-
     } else if (ctx.vR != null) {
-      ExpandSegment seg = new ExpandSegmentRef();
-      expandItemPrev.addSegment(seg);
+      UriInfoImpl resourcePath = (UriInfoImpl) contextExpandItemPath.getPath();
+      resourcePath.addPathInfo(new UriResourceRefImpl());
+
       for (ExpandRefOptionContext s : ctx.vlEOR) {
         list.add((SystemQueryOptionImpl) s.accept(this));
       }
@@ -956,37 +964,27 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
       }
     }
 
-    contextType.pop();
+    contextTypes.pop();
     return list;
 
   }
 
   @Override
-  public Object visitFilter(FilterContext ctx) {
+  public Object visitFilter(final FilterContext ctx) {
 
-    FilterOptionImpl filter = new FilterOptionImpl()
-        .setExpression((ExpressionImpl) ctx.children.get(2).accept(this));
+    FilterOptionImpl filter = new FilterOptionImpl().setExpression((ExpressionImpl) ctx.children.get(2).accept(this));
     return filter;
   }
 
   @Override
-  public Object visitOrderBy(OrderByContext ctx) {
-
-    OrderByOptionImpl orderBy = new OrderByOptionImpl();
-    // TODO collect orders
-    // .setExpression((Expression) ctx.children.get(2).accept(this));
-    return orderBy;
-  }
-
-  @Override
-  public ExpressionImpl visitFloorMethodCallExpr(FloorMethodCallExprContext ctx) {
+  public ExpressionImpl visitFloorMethodCallExpr(final FloorMethodCallExprContext ctx) {
     return new MethodCallImpl()
         .setMethod(SupportedMethodCalls.FLOOR)
         .addParameter((ExpressionImpl) ctx.vE1.accept(this));
   }
 
   @Override
-  public Object visitFormat(FormatContext ctx) {
+  public Object visitFormat(final FormatContext ctx) {
     FormatOptionImpl format = new FormatOptionImpl();
 
     TerminalNodeImpl c2 = (TerminalNodeImpl) ctx.children.get(2);
@@ -1003,62 +1001,50 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
         format.setValue(c2.getText() + "/" + ctx.children.get(4).getText());
       }
     }
+    String text = ctx.children.get(2).getText();
+    if ( ctx.getChildCount()> 4) {
+      text += ctx.children.get(3).getText();
+      text += ctx.children.get(4).getText();
+    }
+    
+    format.setText(text);
+     
 
     return format;
   }
 
   @Override
-  public ExpressionImpl visitFractionalsecondsMethodCallExpr(FractionalsecondsMethodCallExprContext ctx) {
+  public ExpressionImpl visitFractionalsecondsMethodCallExpr(final FractionalsecondsMethodCallExprContext ctx) {
     return new MethodCallImpl()
         .setMethod(SupportedMethodCalls.FRACTIONALSECOND)
         .addParameter((ExpressionImpl) ctx.vE1.accept(this));
   }
 
   @Override
-  public ExpressionImpl visitGeoLengthMethodCallExpr(GeoLengthMethodCallExprContext ctx) {
+  public ExpressionImpl visitGeoLengthMethodCallExpr(final GeoLengthMethodCallExprContext ctx) {
     return new MethodCallImpl()
         .setMethod(SupportedMethodCalls.GEOLENGTH)
         .addParameter((ExpressionImpl) ctx.vE1.accept(this));
   }
 
   @Override
-  public ExpressionImpl visitHourMethodCallExpr(HourMethodCallExprContext ctx) {
+  public ExpressionImpl visitHourMethodCallExpr(final HourMethodCallExprContext ctx) {
     return new MethodCallImpl()
         .setMethod(SupportedMethodCalls.HOUR)
         .addParameter((ExpressionImpl) ctx.vE1.accept(this));
   }
 
   @Override
-  public Object visitId(IdContext ctx) {
+  public Object visitId(final IdContext ctx) {
     IdOptionImpl id = new IdOptionImpl();
-    /*
-     * UriInfoImplResource uriInfoImplpath = new UriInfoImplResource(edm);
-     * 
-     * // store the context uriInfoPath
-     * UriInfoImplResource backupUriInfoPath = this.contextUriInfoPath;
-     * 
-     * // set temporary uriInfoPath to collect the path information of the memberExpression
-     * this.contextUriInfoPath = uriInfoImplpath;
-     * 
-     * ctx.children.get(2).accept(this);
-     * 
-     * this.contextUriInfoPath = backupUriInfoPath;
-     * 
-     * // add the typeFilter which was part of the resource path behind the $entity segment
-     * UriPathInfoImpl lastPathInfo = uriInfoImplpath.getLastUriPathInfo();
-     * EdmStructuralType typeFilter = ((UriInfoImplEntity) this.contextUriInfo).getTypeFilter();
-     * if (typeFilter != null) {
-     * lastPathInfo.addTypeFilter(typeFilter);
-     * }
-     */
-    
-    String text =   ctx.children.get(2).getText();
-        
+
+    String text = ctx.children.get(2).getText();
+
     return id.setValue(text).setText(text);
   }
 
   @Override
-  public ExpressionImpl visitIndexOfMethodCallExpr(IndexOfMethodCallExprContext ctx) {
+  public ExpressionImpl visitIndexOfMethodCallExpr(final IndexOfMethodCallExprContext ctx) {
     return new MethodCallImpl()
         .setMethod(SupportedMethodCalls.INDEXOF)
         .addParameter((ExpressionImpl) ctx.vE1.accept(this))
@@ -1066,7 +1052,16 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
   }
 
   @Override
-  public ExpressionImpl visitIntersectsMethodCallExpr(IntersectsMethodCallExprContext ctx) {
+  public Object visitInlinecount(final InlinecountContext ctx) {
+    InlineCountOptionImpl inlineCount = new InlineCountOptionImpl();
+
+    String text = ctx.children.get(2).getText();
+
+    return inlineCount.setValue(text.equals("true") ? true : false).setText(text);
+  }
+
+  @Override
+  public ExpressionImpl visitIntersectsMethodCallExpr(final IntersectsMethodCallExprContext ctx) {
     return new MethodCallImpl()
         .setMethod(SupportedMethodCalls.GEOLENGTH)
         .addParameter((ExpressionImpl) ctx.vE1.accept(this))
@@ -1074,7 +1069,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
   }
 
   @Override
-  public ExpressionImpl visitIsofExpr(IsofExprContext ctx) {
+  public ExpressionImpl visitIsofExpr(final IsofExprContext ctx) {
     MethodCallImpl method = new MethodCallImpl();
     if (ctx.vE1 != null) {
       ExpressionImpl onExpression = (ExpressionImpl) ctx.vE1.accept(this);
@@ -1090,107 +1085,28 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
   }
 
   @Override
-  public ExpressionImpl visitLengthMethodCallExpr(LengthMethodCallExprContext ctx) {
+  public ExpressionImpl visitLengthMethodCallExpr(final LengthMethodCallExprContext ctx) {
     return new MethodCallImpl()
         .setMethod(SupportedMethodCalls.LENGTH)
         .addParameter((ExpressionImpl) ctx.vE1.accept(this));
   }
 
   @Override
-  public ExpressionImpl visitMaxDateTimeMethodCallExpr(MaxDateTimeMethodCallExprContext ctx) {
+  public ExpressionImpl visitMaxDateTimeMethodCallExpr(final MaxDateTimeMethodCallExprContext ctx) {
     return new MethodCallImpl()
         .setMethod(SupportedMethodCalls.MINDATETIME);
   }
 
   @Override
-  public Object visitRootExpr(RootExprContext ctx) {
-    UriInfoImpl uriInfoImplpath = new UriInfoImpl(edm).setKind(UriInfoKind.resource);
-
-    UriResourceRootImpl pathInfoRoot = new UriResourceRootImpl();
-
-    uriInfoImplpath.addPathInfo(pathInfoRoot);
-
-    if (ctx.vPs != null) {
-      // store the context uriInfoPath
-      UriInfoImpl backupUriInfoPath = this.contextUriInfo;
-
-      // set temporary uriInfoPath to collect the path information of the memberExpression
-      this.contextUriInfo = uriInfoImplpath;
+  public Object visitMemberExpr(final MemberExprContext ctx) {
 
-      ctx.vPs.accept(this);
-
-      this.contextUriInfo = backupUriInfoPath;
-    }
-    return new MemberImpl()
-        .setPath(uriInfoImplpath);
-
-  }
-
-  @Override
-  public Object visitInlinecount(InlinecountContext ctx) {
-    // TODO implement
-    return super.visitInlinecount(ctx);
-  }
-
-  @Override
-  public Object visitAltAny(AltAnyContext ctx) {
-    UriInfoImpl uriInfoImplpath = new UriInfoImpl(edm).setKind(UriInfoKind.resource);
+    UriInfoImpl uriInfoImplpath = new UriInfoImpl().setKind(UriInfoKind.resource);
 
     UriResourceItImpl pathInfoIT = new UriResourceItImpl();
-    pathInfoIT.setType(contextType.peek());
-
-    uriInfoImplpath.addPathInfo(pathInfoIT);
-    uriInfoImplpath.addPathInfo((UriResourcePartImpl) super.visitAltAny(ctx));
+    LastTypeColl lastTypeInfo = this.contextTypes.peek();
+    pathInfoIT.setType(lastTypeInfo.type);
+    pathInfoIT.setCollection(lastTypeInfo.isCollection);
 
-    return new MemberImpl()
-        .setPath(uriInfoImplpath);
-  }
-
-  @Override
-  public Object visitAnyExpr(AnyExprContext ctx) {
-    UriResourceAnyImpl any = new UriResourceAnyImpl();
-    if (ctx.vLV != null) {
-      any.setLamdaVariable(ctx.vLV.getText());
-      lambdaVariables.push(any.getLamdaVariable());
-      any.setExpression((ExpressionImpl) ctx.vLE.accept(this));
-      lambdaVariables.pop();
-    }
-    return any;
-  }
-
-  @Override
-  public Object visitAltAll(AltAllContext ctx) {
-    UriInfoImpl uriInfoImplpath = new UriInfoImpl(edm).setKind(UriInfoKind.resource);
-
-    UriResourceItImpl pathInfoIT = new UriResourceItImpl();
-    pathInfoIT.setType(contextType.peek());
-
-    uriInfoImplpath.addPathInfo(pathInfoIT);
-    uriInfoImplpath.addPathInfo((UriResourcePartImpl) super.visitAltAll(ctx));
-
-    return new MemberImpl()
-        .setPath(uriInfoImplpath);
-  }
-
-  @Override
-  public Object visitAllExpr(AllExprContext ctx) {
-    UriResourceAllImpl all = new UriResourceAllImpl();
-    all.setLamdaVariable(ctx.vLV.getText());
-    lambdaVariables.push(all.getLamdaVariable());
-    all.setExpression((ExpressionImpl) ctx.vLE.accept(this));
-    lambdaVariables.pop();
-    return all;
-  }
-
-  @Override
-  public Object visitMemberExpr(MemberExprContext ctx) {
-
-    UriInfoImpl uriInfoImplpath = new UriInfoImpl(edm).setKind(UriInfoKind.resource);
-
-    UriResourceItImpl pathInfoIT = new UriResourceItImpl();
-    // the start type for members is the final type of the resource path
-    // check wath happens for expand
-    pathInfoIT.setType(contextType.peek());
     if (ctx.vIt != null || ctx.vIts != null) {
       pathInfoIT.setIsExplicitIT(true); // a $it prohibits unbound functions as member expression
     }
@@ -1198,22 +1114,17 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
     uriInfoImplpath.addPathInfo(pathInfoIT);
 
     if (ctx.vPs != null) {
-      // store the context uriInfoPath
-      UriInfoImpl backupUriInfoPath = this.contextUriInfo;
+      // save the context
+      UriInfoImpl backupUriInfoPath = contextUriInfo;
+
+      // set temporary uriInfoPath
+      contextUriInfo = uriInfoImplpath;
 
-      // set temporary uriInfoPath to collect the path information of the memberExpression
-      this.contextUriInfo = uriInfoImplpath;
-      contextDetectedLambda = null;
       ctx.vPs.accept(this);
-      this.contextUriInfo = backupUriInfoPath;
-      if (contextDetectedLambda!= null) {
-        LambdaRefImpl tmp = contextDetectedLambda;
-        contextDetectedLambda = null;
-        return tmp;
-      }
-      
-    }
 
+      // reset context
+      contextUriInfo = backupUriInfoPath;
+    }
 
     if (ctx.vALL != null) {
       uriInfoImplpath.addPathInfo((UriResourcePartImpl) ctx.vALL.accept(this));
@@ -1221,79 +1132,64 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
     if (ctx.vANY != null) {
       uriInfoImplpath.addPathInfo((UriResourcePartImpl) ctx.vANY.accept(this));
     }
-    
 
     return new MemberImpl()
         .setPath(uriInfoImplpath);
   }
 
   @Override
-  public ExpressionImpl visitMinDateTimeMethodCallExpr(MinDateTimeMethodCallExprContext ctx) {
+  public ExpressionImpl visitMinDateTimeMethodCallExpr(final MinDateTimeMethodCallExprContext ctx) {
     return new MethodCallImpl()
         .setMethod(SupportedMethodCalls.MINDATETIME);
   }
 
   @Override
-  public ExpressionImpl visitMinuteMethodCallExpr(MinuteMethodCallExprContext ctx) {
+  public ExpressionImpl visitMinuteMethodCallExpr(final MinuteMethodCallExprContext ctx) {
     return new MethodCallImpl()
         .setMethod(SupportedMethodCalls.MINUTE)
         .addParameter((ExpressionImpl) ctx.vE1.accept(this));
   }
 
   @Override
-  public ExpressionImpl visitMonthMethodCallExpr(MonthMethodCallExprContext ctx) {
+  public ExpressionImpl visitMonthMethodCallExpr(final MonthMethodCallExprContext ctx) {
     return new MethodCallImpl()
         .setMethod(SupportedMethodCalls.MONTH)
         .addParameter((ExpressionImpl) ctx.vE1.accept(this));
   }
 
   @Override
-  public Object visitNameValueOptList(NameValueOptListContext ctx) {
+  public Object visitNameValueOptList(final NameValueOptListContext ctx) {
 
     // is key predicate
     if (ctx.vVO != null) {
-      String text = ctx.vVO.vV.getText();
+      String valueText = ctx.vVO.vV.getText();
       ExpressionImpl expression = (ExpressionImpl) ctx.vVO.vV.accept(this);
 
-      if (!(contextUriInfo.getLastUriPathInfo() instanceof UriResourceImplTyped)) {
-        throw wrap(new UriParserSyntaxException("Invalid Paramterslist"));
+      if (!(contextUriInfo.getLastResourcePart() instanceof UriResourceImplTyped)) {
+        throw wrap(new UriParserSyntaxException("Paramterslist on untyped resource path segement not allowed"));
       }
 
-      EdmEntityType entityType = (EdmEntityType) ((UriResourceImplTyped) contextUriInfo.getLastUriPathInfo()).getType();
+      EdmEntityType entityType =
+          (EdmEntityType) ((UriResourceImplTyped) contextUriInfo.getLastResourcePart()).getType();
 
       List<String> keyPredicates = entityType.getKeyPredicateNames();
       if (keyPredicates.size() == 1) {
         String keyName = keyPredicates.get(0);
         List<UriParameterImpl> list = new ArrayList<UriParameterImpl>();
-        list.add(new UriParameterImpl().setName(keyName).setText(text).setExpression(expression));
+        list.add(new UriParameterImpl().setName(keyName).setText(valueText).setExpression(expression));
         return list;
       }
 
-      // if there is only a single key in the URI but there are more than one keys defined in the EDM, then reduce
-      // the keylist with the keys defined as referential constained.
-
-      if (contextUriInfo.getLastUriPathInfo() instanceof UriResourceNavigationPropertyImpl) {
-        UriResourceNavigationPropertyImpl nav = (UriResourceNavigationPropertyImpl) contextUriInfo.getLastUriPathInfo();
-        EdmNavigationProperty navProp = (EdmNavigationProperty) nav.getNavigationProperty();
-        /*
-         * if ( navProp.getPartner() != null) {
-         * //copy keylist into tmpKeyList
-         * 
-         * EdmEntityType entityType = nav.getType()// TODO check typecast,
-         * EdmNavigationProperty navProp2 = entityType.getProperty(navProp.getPartner());
-         * for ( EdmRefConstrain constrain : navProp2 ) {
-         * //remove constrain.referenceproperty from tmpKeyList
-         * }
-         * 
-         * if( tmpKeyList.size==1)
-         * String keyName = keyPredicates.get(0);
-         * List<UriParameterImpl> list = new ArrayList<UriParameterImpl>();
-         * list.add(new UriParameterImpl().setName(keyName).setValue(value));
-         * return list;
-         * }
-         * }
-         */
-      }
+      // If there is only a single key in the URI but there are more than one keys defined in the EDM, then reduce
+      // The keylist with the keys defined as referential constrained.
+      // TODO add support vor using refential constrains
+      /*
+       * if (contextUriInfo.getLastResourcePart() instanceof UriResourceNavigationPropertyImpl) {
+       * UriResourceNavigationPropertyImpl nav =
+       * (UriResourceNavigationPropertyImpl) contextUriInfo.getLastResourcePart();
+       * nav.getNavigationProperty();
+       * }
+       */
 
       throw wrap(new UriParserSyntaxException(
           "for using a value only keyPredicate there must be exact ONE defined keyProperty"));
@@ -1311,7 +1207,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
   }
 
   @Override
-  public UriParameterImpl visitNameValuePair(NameValuePairContext ctx) {
+  public UriParameterImpl visitNameValuePair(final NameValuePairContext ctx) {
     UriParameterImpl uriParameter = new UriParameterImpl();
     uriParameter.setName(ctx.vODI.getText());
 
@@ -1326,32 +1222,38 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
   }
 
   @Override
-  public ExpressionImpl visitNowMethodCallExpr(NowMethodCallExprContext ctx) {
+  public ExpressionImpl visitNowMethodCallExpr(final NowMethodCallExprContext ctx) {
     return new MethodCallImpl()
         .setMethod(SupportedMethodCalls.NOW);
   }
 
   @Override
-  public Object visitOdataRelativeUriEOF(OdataRelativeUriEOFContext ctx) {
-    // setup context
-    this.contextUriInfo = null;
-    // visit children
+  public Object visitOdataRelativeUriEOF(final OdataRelativeUriEOFContext ctx) {
+    contextUriInfo = null;
     super.visitOdataRelativeUriEOF(ctx);
+    return contextUriInfo;
+  }
 
-    return this.contextUriInfo;
+  @Override
+  public Object visitOrderBy(final OrderByContext ctx) {
+
+    OrderByOptionImpl orderBy = new OrderByOptionImpl();
+    // TODO collect orders
+    // .setExpression((Expression) ctx.children.get(2).accept(this));
+    return orderBy;
   }
 
   @Override
-  public Object visitPathSegment(PathSegmentContext ctx) {
+  public Object visitPathSegment(final PathSegmentContext ctx) {
 
-    if (contextUriInfo.getLastUriPathInfo() == null ||
-        contextUriInfo.getLastUriPathInfo() instanceof UriResourceRootImpl) {
+    if (contextUriInfo.getLastResourcePart() == null ||
+        contextUriInfo.getLastResourcePart() instanceof UriResourceRootImpl) {
       readFirstPathInfoSegment(ctx);
     } else {
       readNextPathInfoSegment(ctx);
     }
 
-    UriResourcePartImpl pathInfoSegment = (UriResourcePartImpl) this.contextUriInfo.getLastUriPathInfo();
+    UriResourcePartImpl pathInfoSegment = (UriResourcePartImpl) contextUriInfo.getLastResourcePart();
 
     if (ctx.vlNVO.size() > 0) {
       // check for keyPredicates
@@ -1369,7 +1271,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
   }
 
   @Override
-  public Object visitPathSegments(PathSegmentsContext ctx) {
+  public Object visitPathSegments(final PathSegmentsContext ctx) {
     // path segment
     for (PathSegmentContext it : ctx.vlPS) {
       it.accept(this);
@@ -1383,57 +1285,8 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
   }
 
   @Override
-  public Object visitConstSegment(ConstSegmentContext ctx) {
-    UriInfoImpl uriInfoResource = this.contextUriInfo;
-    UriResourcePart pathInfo = uriInfoResource.getLastUriPathInfo();
+  public Object visitQueryOptions(final QueryOptionsContext ctx) {
 
-    if (ctx.vV != null) {
-      if (pathInfo instanceof UriResourcePartTyped) {
-        if (!((UriResourcePartTyped) pathInfo).isCollection()) {
-          this.contextUriInfo.addPathInfo(new UriResourceValueImpl());
-        } else {
-          throw wrap(new UriParserSemanticException("$value only allowed on typed path segments"));
-        }
-        return null;
-      } else {
-        throw wrap(new UriParserSemanticException("$value only allowed on typed path segments"));
-      }
-
-    } else if (ctx.vC != null) {
-      if (pathInfo instanceof UriResourceImplTyped) {
-        if (((UriResourceImplTyped) pathInfo).isCollection()) {
-          this.contextUriInfo.addPathInfo(new UriResourceCountImpl());
-        } else {
-          throw wrap(new UriParserSemanticException("$count only allowed on collection properties"));
-        }
-      } else {
-        throw wrap(new UriParserSemanticException("$count only allowed on typed properties"));
-      }
-    } else if (ctx.vR != null) {
-      if (pathInfo instanceof UriResourceImplTyped) {
-        EdmType type = ((UriResourceImplTyped) pathInfo).getType();
-        if (type instanceof EdmEntityType) {
-          this.contextUriInfo.addPathInfo(new UriResourceRefImpl());
-        } else {
-          throw wrap(new UriParserSemanticException("$ref only allowd on endity types"));
-        }
-      } else {
-        throw wrap(new UriParserSemanticException("$ref only allowed on typed properties"));
-      }
-
-    }
-    return null;
-  }
-
-  @Override
-  public Object visitQueryOptions(QueryOptionsContext ctx) {
-    if (contextType == null) {
-      contextType = new Stack<EdmType>();
-
-    }
-    // contextType.push(this.contextUriInfo.getLastUriPathInfo().getType());
-
-    // QueryOptionsList qpList = new QueryOptionsList();
     List<QueryOptionImpl> qpList = new ArrayList<QueryOptionImpl>();
     for (QueryOptionContext entityOption : ctx.vlQO) {
       qpList.add((QueryOptionImpl) entityOption.accept(this));
@@ -1443,35 +1296,59 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
   }
 
   @Override
-  public Object visitResourcePath(ResourcePathContext ctx) {
+  public Object visitResourcePath(final ResourcePathContext ctx) {
     if (ctx.vAll != null) {
-      this.contextUriInfo = new UriInfoImpl(edm).setKind(UriInfoKind.all);
+      contextUriInfo = new UriInfoImpl().setKind(UriInfoKind.all);
     } else if (ctx.vCJ != null) {
       ctx.vCJ.accept(this);
     } else if (ctx.vlPS != null) {
-      UriInfoImpl uriInfoPath = new UriInfoImpl(edm).setKind(UriInfoKind.resource);
-      this.contextUriInfo = uriInfoPath;
+      UriInfoImpl uriInfoPath = new UriInfoImpl().setKind(UriInfoKind.resource);
+      contextUriInfo = uriInfoPath;
       super.visitResourcePath(ctx); // visit all children of ctx
     }
-    return this.contextUriInfo;
+    return contextUriInfo;
+  }
+
+  @Override
+  public Object visitRootExpr(final RootExprContext ctx) {
+    UriInfoImpl uriInfoImplpath = new UriInfoImpl().setKind(UriInfoKind.resource);
+
+    UriResourceRootImpl pathInfoRoot = new UriResourceRootImpl();
+
+    uriInfoImplpath.addPathInfo(pathInfoRoot);
+
+    if (ctx.vPs != null) {
+      // store the context uriInfoPath
+      UriInfoImpl backupUriInfoPath = contextUriInfo;
+
+      // set temporary uriInfoPath to collect the path information of the memberExpression
+      contextUriInfo = uriInfoImplpath;
+
+      ctx.vPs.accept(this);
+
+      contextUriInfo = backupUriInfoPath;
+    }
+    return new MemberImpl()
+        .setPath(uriInfoImplpath);
+
   }
 
   @Override
-  public ExpressionImpl visitRoundMethodCallExpr(RoundMethodCallExprContext ctx) {
+  public ExpressionImpl visitRoundMethodCallExpr(final RoundMethodCallExprContext ctx) {
     return new MethodCallImpl()
         .setMethod(SupportedMethodCalls.ROUND)
         .addParameter((ExpressionImpl) ctx.vE1.accept(this));
   }
 
   @Override
-  public ExpressionImpl visitSecondMethodCallExpr(SecondMethodCallExprContext ctx) {
+  public ExpressionImpl visitSecondMethodCallExpr(final SecondMethodCallExprContext ctx) {
     return new MethodCallImpl()
         .setMethod(SupportedMethodCalls.SECOND)
         .addParameter((ExpressionImpl) ctx.vE1.accept(this));
   }
 
   @Override
-  public Object visitSelect(SelectContext ctx) {
+  public Object visitSelect(final SelectContext ctx) {
     List<SelectItemOptionImpl> selectItems = new ArrayList<SelectItemOptionImpl>();
 
     for (SelectItemContext si : ctx.vlSI) {
@@ -1482,10 +1359,8 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
   }
 
   @Override
-  public Object visitSelectItem(SelectItemContext ctx) {
+  public Object visitSelectItem(final SelectItemContext ctx) {
     SelectItemOptionImpl selectItem = new SelectItemOptionImpl();
-    selectItem.setEdm(edm);
-    selectItem.setStartType(contextType.peek());
 
     contextSelectItem = selectItem;
     for (SelectSegmentContext si : ctx.vlSS) {
@@ -1497,7 +1372,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
   }
 
   @Override
-  public Object visitSelectSegment(SelectSegmentContext ctx) {
+  public Object visitSelectSegment(final SelectSegmentContext ctx) {
 
     if (ctx.vS != null) {
       if (ctx.vNS != null) {
@@ -1514,28 +1389,109 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
     String odi = ctx.vODI.getText();
     if (ctx.vNS == null) {
 
-      contextSelectItem.addProperty(odi);
+      EdmType prevType = contextSelectItem.getType();
+      if (prevType == null) {
+        prevType = this.contextTypes.peek().type;
+      }
+
+      if (!(prevType instanceof EdmStructuralType)) {
+        throw wrap(new UriParserSemanticException("Previous select item is not a structural type"));
+      }
+
+      EdmStructuralType structType = (EdmStructuralType) prevType;
+      EdmElement property = (EdmElement) structType.getProperty(odi);
+      if (property == null) {
+        throw wrap(new UriParserSemanticException("Previous select item has not property: " + odi));
+
+      }
+
+      // create new segment
+      SelectSegmentImpl newSegment = new SelectSegmentImpl().setProperty(property);
+      contextSelectItem.addSegment(newSegment);
+
+      return this;
 
     } else {
       String namespace = ctx.vNS.getText();
       namespace = namespace.substring(0, namespace.length() - 1);
 
       FullQualifiedName fullName = new FullQualifiedName(namespace, odi);
-      contextSelectItem.addQualifiedThing(fullName);
+      // contextSelectItem.addQualifiedThing(fullName);
+
+      EdmType prevType = contextSelectItem.getType();
+      if (prevType != null) { // context types required at least one property
+        if (prevType instanceof EdmComplexType) {
+          EdmComplexType ct = edm.getComplexType(fullName);
+          if (ct != null) {
+            if (((EdmStructuralType) prevType).compatibleTo(ct)) {
+              SelectSegmentImpl lastSegment = contextSelectItem.getLastSegment();
+              lastSegment.setTypeCast(ct);
+              return this;
+            }
+          }
+        }
+      } else {
+        prevType = this.contextTypes.peek().type;
+        if (prevType instanceof EdmEntityType) {
+          EdmEntityType et = edm.getEntityType(fullName);
+          if (((EdmStructuralType) prevType).compatibleTo(et)) {
+            contextSelectItem.setEntityTypeCast(et);
+            return this;
+          }
+        }
+      }
+
+      FullQualifiedName finalTypeName = new FullQualifiedName(prevType.getNamespace(), prevType.getName());
+
+      // check for action
+      EdmAction action = edm.getAction(fullName, finalTypeName, null);
+      // TODO verify that null ignores if it is a collection
+
+      if (action != null) {
+        contextSelectItem.addSegment(new SelectSegmentImpl().setAction(action));
+      }
+
+      // check for function
+      EdmFunction function = edm.getFunction(fullName, finalTypeName, null, null);
+      // TODO verify that null ignores if it is a collection
+
+      if (function != null) {
+        contextSelectItem.addSegment(new SelectSegmentImpl().setFunction(function));
+      }
+
     }
 
     return null;
   }
 
+  
+  @Override
+  public Object visitSkip(SkipContext ctx) {
+    SkipOptionImpl skiptoken = new SkipOptionImpl();
+
+    String text = ctx.children.get(2).getText();
+
+    return skiptoken.setValue(text).setText(text);
+  }
+
   @Override
-  public ExpressionImpl visitStartsWithMethodCallExpr(StartsWithMethodCallExprContext ctx) {
+  public Object visitSkiptoken(SkiptokenContext ctx) {
+    SkiptokenOptionImpl skiptoken = new SkiptokenOptionImpl();
+
+    String text = ctx.children.get(2).getText();
+
+    return skiptoken.setValue(text).setText(text);
+  }
+
+  @Override
+  public ExpressionImpl visitStartsWithMethodCallExpr(final StartsWithMethodCallExprContext ctx) {
     return new MethodCallImpl()
         .setMethod(SupportedMethodCalls.STARTSWITH)
         .addParameter((ExpressionImpl) ctx.vE1.accept(this));
   }
 
   @Override
-  public ExpressionImpl visitSubstringMethodCallExpr(SubstringMethodCallExprContext ctx) {
+  public ExpressionImpl visitSubstringMethodCallExpr(final SubstringMethodCallExprContext ctx) {
     MethodCallImpl ret = new MethodCallImpl();
     ret.setMethod(SupportedMethodCalls.SUBSTRING);
     ret.addParameter((ExpressionImpl) ctx.vE1.accept(this));
@@ -1550,69 +1506,72 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
   }
 
   @Override
-  public ExpressionImpl visitTimeMethodCallExpr(TimeMethodCallExprContext ctx) {
+  public ExpressionImpl visitTimeMethodCallExpr(final TimeMethodCallExprContext ctx) {
     return new MethodCallImpl()
         .setMethod(SupportedMethodCalls.TIME)
         .addParameter((ExpressionImpl) ctx.vE1.accept(this));
   }
 
+  
+  @Override
+  public Object visitTop(TopContext ctx) {
+    TopOptionImpl top = new TopOptionImpl();
+
+    String text = ctx.children.get(2).getText();
+
+    return top.setValue(text).setText(text);
+  }
+
   @Override
-  public ExpressionImpl visitToLowerMethodCallExpr(ToLowerMethodCallExprContext ctx) {
+  public ExpressionImpl visitToLowerMethodCallExpr(final ToLowerMethodCallExprContext ctx) {
     return new MethodCallImpl()
         .setMethod(SupportedMethodCalls.TOLOWER)
         .addParameter((ExpressionImpl) ctx.vE1.accept(this));
   }
 
   @Override
-  public ExpressionImpl visitTotalOffsetMinutesMethodCallExpr(TotalOffsetMinutesMethodCallExprContext ctx) {
+  public ExpressionImpl visitTotalOffsetMinutesMethodCallExpr(final TotalOffsetMinutesMethodCallExprContext ctx) {
     return new MethodCallImpl()
         .setMethod(SupportedMethodCalls.TOTALOFFSETMINUTES)
         .addParameter((ExpressionImpl) ctx.vE1.accept(this));
   }
 
   @Override
-  public ExpressionImpl visitTotalsecondsMethodCallExpr(TotalsecondsMethodCallExprContext ctx) {
+  public ExpressionImpl visitTotalsecondsMethodCallExpr(final TotalsecondsMethodCallExprContext ctx) {
     return new MethodCallImpl()
         .setMethod(SupportedMethodCalls.TOTALSECONDS)
         .addParameter((ExpressionImpl) ctx.vE1.accept(this));
   }
 
   @Override
-  public ExpressionImpl visitToUpperMethodCallExpr(ToUpperMethodCallExprContext ctx) {
+  public ExpressionImpl visitToUpperMethodCallExpr(final ToUpperMethodCallExprContext ctx) {
     return new MethodCallImpl()
         .setMethod(SupportedMethodCalls.TOUPPER)
         .addParameter((ExpressionImpl) ctx.vE1.accept(this));
   }
 
   @Override
-  public ExpressionImpl visitTrimMethodCallExpr(TrimMethodCallExprContext ctx) {
+  public ExpressionImpl visitTrimMethodCallExpr(final TrimMethodCallExprContext ctx) {
     return new MethodCallImpl()
         .setMethod(SupportedMethodCalls.TRIM)
         .addParameter((ExpressionImpl) ctx.vE1.accept(this));
   }
 
   @Override
-  public Object visitUnary(UnaryContext ctx) {
+  public Object visitUnary(final UnaryContext ctx) {
     // TODO implement
     return super.visitUnary(ctx);
   }
 
   @Override
-  public ExpressionImpl visitYearMethodCallExpr(YearMethodCallExprContext ctx) {
+  public ExpressionImpl visitYearMethodCallExpr(final YearMethodCallExprContext ctx) {
     return new MethodCallImpl()
         .setMethod(SupportedMethodCalls.YEAR)
         .addParameter((ExpressionImpl) ctx.vE1.accept(this));
   }
 
-  private FullQualifiedName getFullName(NamespaceContext vNS, String odi) {
-    if (vNS != null) {
-      String namespace = vNS.getText();
-      namespace = namespace.substring(0, namespace.length() - 1);
-
-      return new FullQualifiedName(namespace, odi);
-    }
-    return null;
-
+  private ParseCancellationException wrap(final UriParserException uriParserException) {
+    return new ParseCancellationException(uriParserException);
   }
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/blob/1ef03f92/odata4-lib/odata4-producer-core/src/main/java/org/apache/olingo/odata4/producer/core/uri/UriParserException.java
----------------------------------------------------------------------
diff --git a/odata4-lib/odata4-producer-core/src/main/java/org/apache/olingo/odata4/producer/core/uri/UriParserException.java b/odata4-lib/odata4-producer-core/src/main/java/org/apache/olingo/odata4/producer/core/uri/UriParserException.java
index f4780c3..e766d68 100644
--- a/odata4-lib/odata4-producer-core/src/main/java/org/apache/olingo/odata4/producer/core/uri/UriParserException.java
+++ b/odata4-lib/odata4-producer-core/src/main/java/org/apache/olingo/odata4/producer/core/uri/UriParserException.java
@@ -23,16 +23,14 @@ public class UriParserException extends Exception {
   /**
    * 
    */
-  private static final long serialVersionUID = -1813203179082217112L;
+  private static final long serialVersionUID = 1L;
 
-  public UriParserException(String message, Throwable cause) {
+  public UriParserException(final String message, final Throwable cause) {
     super(message, cause);
   }
 
-  public UriParserException(String message) {
+  public UriParserException(final String message) {
     super(message, null);
   }
 
-  
-
 }