/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.olingo.server.core.uri.parser;

import org.antlr.v4.runtime.misc.NotNull;
import org.antlr.v4.runtime.misc.ParseCancellationException;
import org.antlr.v4.runtime.tree.ParseTree;
import org.apache.olingo.commons.api.edm.Edm;
import org.apache.olingo.commons.api.edm.EdmAction;
import org.apache.olingo.commons.api.edm.EdmActionImport;
import org.apache.olingo.commons.api.edm.EdmComplexType;
import org.apache.olingo.commons.api.edm.EdmElement;
import org.apache.olingo.commons.api.edm.EdmEntityContainer;
import org.apache.olingo.commons.api.edm.EdmEntitySet;
import org.apache.olingo.commons.api.edm.EdmEntityType;
import org.apache.olingo.commons.api.edm.EdmEnumType;
import org.apache.olingo.commons.api.edm.EdmFunction;
import org.apache.olingo.commons.api.edm.EdmFunctionImport;
import org.apache.olingo.commons.api.edm.EdmNavigationProperty;
import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
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.FullQualifiedName;
import org.apache.olingo.commons.core.edm.primitivetype.EdmPrimitiveTypeFactory;
import org.apache.olingo.server.api.uri.UriInfoKind;
import org.apache.olingo.server.api.uri.UriResource;
import org.apache.olingo.server.api.uri.UriResourcePartTyped;
import org.apache.olingo.server.api.uri.queryoption.expression.BinaryOperatorKind;
import org.apache.olingo.server.api.uri.queryoption.expression.MethodKind;
import org.apache.olingo.server.api.uri.queryoption.expression.UnaryOperatorKind;
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;
import org.apache.olingo.server.core.uri.UriResourceEntitySetImpl;
import org.apache.olingo.server.core.uri.UriResourceFunctionImpl;
import org.apache.olingo.server.core.uri.UriResourceImpl;
import org.apache.olingo.server.core.uri.UriResourceItImpl;
import org.apache.olingo.server.core.uri.UriResourceLambdaAllImpl;
import org.apache.olingo.server.core.uri.UriResourceLambdaAnyImpl;
import org.apache.olingo.server.core.uri.UriResourceLambdaVarImpl;
import org.apache.olingo.server.core.uri.UriResourceNavigationPropertyImpl;
import org.apache.olingo.server.core.uri.UriResourcePrimitivePropertyImpl;
import org.apache.olingo.server.core.uri.UriResourceRefImpl;
import org.apache.olingo.server.core.uri.UriResourceRootImpl;
import org.apache.olingo.server.core.uri.UriResourceSingletonImpl;
import org.apache.olingo.server.core.uri.UriResourceStartingTypeFilterImpl;
import org.apache.olingo.server.core.uri.UriResourceTypedImpl;
import org.apache.olingo.server.core.uri.UriResourceValueImpl;
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.UriParserBaseVisitor;
import org.apache.olingo.server.core.uri.antlr.UriParserParser;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.AllEOFContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.AllExprContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.AltAddContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.AltAllContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.AltAndContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.AltAnyContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.AltComparismContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.AltEqualityContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.AltHasContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.AltMultContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.AltOrContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.AnyExprContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.BatchEOFContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.BooleanNonCaseContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.CastExprContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.CeilingMethodCallExprContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.ConcatMethodCallExprContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.ConstSegmentContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.ContainsMethodCallExprContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.CrossjoinEOFContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.DateMethodCallExprContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.DayMethodCallExprContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.EndsWithMethodCallExprContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.EntityEOFContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.EnumLitContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.ExpandCountOptionContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.ExpandItemContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.ExpandItemsContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.ExpandOptionContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.ExpandPathContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.ExpandPathExtensionContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.ExpandRefOptionContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.FilterContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.FilterExpressionEOFContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.FloorMethodCallExprContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.FractionalsecondsMethodCallExprContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.GeoDistanceMethodCallExprContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.GeoIntersectsMethodCallExprContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.GeoLengthMethodCallExprContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.HourMethodCallExprContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.IndexOfMethodCallExprContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.InlinecountContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.IsofExprContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.LengthMethodCallExprContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.LevelsContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.MaxDateTimeMethodCallExprContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.MemberExprContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.MetadataEOFContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.MinDateTimeMethodCallExprContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.MinuteMethodCallExprContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.MonthMethodCallExprContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.NameValueOptListContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.NameValuePairContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.NamespaceContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.NaninfinityContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.NowMethodCallExprContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.NullruleContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.OdataIdentifierContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.OrderByContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.OrderByEOFContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.OrderByItemContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.OrderListContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.PathSegmentContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.PathSegmentsContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.PrimitiveLiteralContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.QueryOptionContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.QueryOptionsContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.RootExprContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.RoundMethodCallExprContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.SecondMethodCallExprContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.SelectContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.SelectEOFContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.SelectItemContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.SelectSegmentContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.SkipContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.SkiptokenContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.StartsWithMethodCallExprContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.SubstringMethodCallExprContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.TimeMethodCallExprContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.ToLowerMethodCallExprContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.ToUpperMethodCallExprContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.TopContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.TotalOffsetMinutesMethodCallExprContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.TotalsecondsMethodCallExprContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.TrimMethodCallExprContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.YearMethodCallExprContext;
import org.apache.olingo.server.core.uri.queryoption.CountOptionImpl;
import org.apache.olingo.server.core.uri.queryoption.ExpandItemImpl;
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.LevelsOptionImpl;
import org.apache.olingo.server.core.uri.queryoption.OrderByItemImpl;
import org.apache.olingo.server.core.uri.queryoption.OrderByOptionImpl;
import org.apache.olingo.server.core.uri.queryoption.QueryOptionImpl;
import org.apache.olingo.server.core.uri.queryoption.SelectItemImpl;
import org.apache.olingo.server.core.uri.queryoption.SelectOptionImpl;
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.SystemQueryOptionImpl;
import org.apache.olingo.server.core.uri.queryoption.TopOptionImpl;
import org.apache.olingo.server.core.uri.queryoption.expression.AliasImpl;
import org.apache.olingo.server.core.uri.queryoption.expression.BinaryImpl;
import org.apache.olingo.server.core.uri.queryoption.expression.EnumerationImpl;
import org.apache.olingo.server.core.uri.queryoption.expression.ExpressionImpl;
import org.apache.olingo.server.core.uri.queryoption.expression.LiteralImpl;
import org.apache.olingo.server.core.uri.queryoption.expression.MemberImpl;
import org.apache.olingo.server.core.uri.queryoption.expression.MethodImpl;
import org.apache.olingo.server.core.uri.queryoption.expression.TypeLiteralImpl;
import org.apache.olingo.server.core.uri.queryoption.expression.UnaryImpl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * UriVisitor
 * 
 * Converts the URI parse tree the generated by ANTLR into an internal representation which maybe is given to the
 * application. While converting the tree is only validated against the EDM if necessary.
 * 
 * Attention:
 * <li> This UriVisitor is at somes point more lax than the original ABNF
 * <li> It is more tolerable against additional white spaces Currently not supported
 * <li>Parsing the context of $metadata</li>
 * <li>Parsing $search</li>
 */
public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {

  public class TypeInformation {

    boolean isCollection;

    EdmType type;

    TypeInformation(final EdmType type, final boolean isCollection) {
      this.type = type;
      this.isCollection = isCollection;
    }

    public TypeInformation() {}
  }

  public UriContext context = null;

  public Edm edm;

  public EdmEntityContainer edmEntityContainer;

  // --- class ---
  public UriParseTreeVisitor(final Edm edm, final UriContext context) {
    this.edm = edm;
    this.context = context;
    edmEntityContainer = edm.getEntityContainer(null);
  }

  @Override
  protected Object aggregateResult(final Object aggregate, final Object nextResult) {
    if (aggregate != null) {
      return aggregate;
    } else {
      return nextResult;
    }
  }

  private FullQualifiedName getFullNameFromContext(final NamespaceContext vNS, final String odi) {
    String namespace = vNS.getText();
    namespace = namespace.substring(0, namespace.length() - 1); // vNS contains a trailing point that has to be removed
    return new FullQualifiedName(namespace, odi);
  }

  private UriContext.LambdaVariables getLambdaVar(final String odi) {
    for (UriContext.LambdaVariables item : context.allowedLambdaVariables) {
      if (item.name.equals(odi)) {
        return item;
      }
    }
    return null;
  }

  TypeInformation getTypeInformation(final UriResource lastResourcePart) {

    TypeInformation typeInformation = new TypeInformation();
    if (lastResourcePart instanceof UriResourceWithKeysImpl) {
      UriResourceWithKeysImpl lastPartWithKeys = (UriResourceWithKeysImpl) lastResourcePart;

      if (lastPartWithKeys.getTypeFilterOnEntry() != null) {
        typeInformation.type = lastPartWithKeys.getTypeFilterOnEntry();
      } else if (lastPartWithKeys.getTypeFilterOnCollection() != null) {
        typeInformation.type = lastPartWithKeys.getTypeFilterOnCollection();
      } else {
        typeInformation.type = lastPartWithKeys.getType();
      }
      typeInformation.isCollection = lastPartWithKeys.isCollection();

    } else if (lastResourcePart instanceof UriResourceTypedImpl) {
      UriResourceTypedImpl lastPartTyped = (UriResourceTypedImpl) lastResourcePart;

      if (lastPartTyped.getTypeFilter() != null) {
        typeInformation.type = lastPartTyped.getTypeFilter();
      } else {
        typeInformation.type = lastPartTyped.getType();
      }

      typeInformation.isCollection = lastPartTyped.isCollection();
    }

    return typeInformation;
  }

  public UriResourceTypedImpl readResourcePathSegment(final PathSegmentContext ctx) {

    final boolean checkFirst =
        context.contextUriInfo.getLastResourcePart() == null
        || context.contextUriInfo.getLastResourcePart() instanceof UriResourceRootImpl;

    String odi = ctx.vODI.getText();

    if (checkFirst && ctx.vNS == null) {

      // check EntitySet
      EdmEntitySet edmEntitySet = edmEntityContainer.getEntitySet(odi);
      if (edmEntitySet != null) {
        UriResourceEntitySetImpl uriResource = new UriResourceEntitySetImpl()
            .setEntitSet(edmEntitySet);
        context.contextUriInfo.addResourcePart(uriResource);
        return null;
      }

      // check Singleton
      EdmSingleton edmSingleton = edmEntityContainer.getSingleton(odi);
      if (edmSingleton != null) {
        UriResourceSingletonImpl uriResource = new UriResourceSingletonImpl()
            .setSingleton(edmSingleton);
        context.contextUriInfo.addResourcePart(uriResource);
        return null;
      }

      // check ActionImport
      EdmActionImport edmActionImport = edmEntityContainer.getActionImport(odi);
      if (edmActionImport != null) {
        UriResourceActionImpl uriResource = new UriResourceActionImpl()
            .setActionImport(edmActionImport);
        context.contextUriInfo.addResourcePart(uriResource);
        return null;
      }

      // check FunctionImport
      EdmFunctionImport edmFunctionImport = edmEntityContainer.getFunctionImport(odi);
      if (edmFunctionImport != null) {

        // read the URI parameters
        context.contextReadingFunctionParameters = true;
        @SuppressWarnings("unchecked")
        List<UriParameterImpl> parameters = (List<UriParameterImpl>) ctx.vlNVO.get(0).accept(this);
        context.contextReadingFunctionParameters = false;

        // 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 (UriParameterImpl item : parameters) {
          names.add(item.getName());
        }

        // get function from function import
        EdmFunction function = edmFunctionImport.getUnboundFunction(names);
        if (function == null) {
          String tmp = "";
          for (String name : names) {
            tmp += (tmp.length() != 0 ? "," : "") + name;
          }
          throw wrap(new UriParserSemanticException("Function of functionimport '" + edmFunctionImport.getName()
              + "' with parameters [" + tmp + "] not found",
              UriParserSemanticException.MessageKeys.FUNCTION_NOT_FOUND, edmFunctionImport.getName(), tmp));
        }

        uriResource.setFunction(edmFunctionImport.getUnboundFunction(names));
        context.contextUriInfo.addResourcePart(uriResource);
        return null;
      }
    }

    TypeInformation source = null;
    UriResource lastResourcePart = context.contextUriInfo.getLastResourcePart();

    if (lastResourcePart == null) {
      if (context.contextTypes.size() == 0) {
        if(checkFirst && ctx.vNS == null){
          throw wrap(new UriParserSemanticException(
              "Cannot find EntitySet, Singleton, ActionImport or FunctionImport with name '" + odi + "'.",
              UriParserSemanticException.MessageKeys.RESOURCE_NOT_FOUND, odi));
        }
        throw wrap(new UriParserSemanticException("Resource part '" + odi + "' can only applied on typed "
            + "resource parts",
            UriParserSemanticException.MessageKeys.RESOURCE_PART_ONLY_FOR_TYPED_PARTS, odi));
      }
      source = context.contextTypes.peek();
    } else {
      source = getTypeInformation(lastResourcePart);

      if (source.type == null) {
        throw wrap(new UriParserSemanticException("Resource part '" + odi + "' can only be applied on typed "
            + "resource parts.", UriParserSemanticException.MessageKeys.RESOURCE_PART_ONLY_FOR_TYPED_PARTS, odi));
      }
    }

    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);
      if (lVar != null) {
        UriResourceLambdaVarImpl lambdaResource = new UriResourceLambdaVarImpl();
        lambdaResource.setVariableText(lVar.name);
        lambdaResource.setType(lVar.type);
        lambdaResource.setCollection(lVar.isCollection);
        context.contextUriInfo.addResourcePart(lambdaResource);
        return null;
      }

      if (!(source.type instanceof EdmStructuredType)) {
        throw wrap(new UriParserSemanticException("Cannot parse '" + odi
            + "'; previous path segment is not a structural type.",
            UriParserSemanticException.MessageKeys.RESOURCE_PART_MUST_BE_PRECEDED_BY_STRUCTURAL_TYPE, odi));
      }

      if (ctx.depth() <= 2  // path evaluation for the resource path
          && source.isCollection) {
        throw wrap(new UriParserSemanticException("Property '" + odi + "' is not allowed after collection.",
            UriParserSemanticException.MessageKeys.PROPERTY_AFTER_COLLECTION, odi));
      }

      EdmStructuredType structType = (EdmStructuredType) source.type;

      EdmElement property = structType.getProperty(odi);
      if (property == null) {
        throw wrap(new UriParserSemanticException("Property '" + odi + "' not found in type '"
            + structType.getNamespace() + "." + structType.getName() + "'",
            ctx.depth() > 2 ?  // path evaluation inside an expression or for the resource path?
                UriParserSemanticException.MessageKeys.EXPRESSION_PROPERTY_NOT_IN_TYPE :
                UriParserSemanticException.MessageKeys.PROPERTY_NOT_IN_TYPE,
            structType.getFullQualifiedName().toString(), odi));
      }

      if (property instanceof EdmProperty) {
        if (((EdmProperty) property).isPrimitive() == true) {
          // create simple property
          UriResourcePrimitivePropertyImpl simpleResource = new UriResourcePrimitivePropertyImpl()
              .setProperty((EdmProperty) property);
          context.contextUriInfo.addResourcePart(simpleResource);
          return null;
        } else {
          // create complex property
          UriResourceComplexPropertyImpl complexResource = new UriResourceComplexPropertyImpl()
              .setProperty((EdmProperty) property);
          context.contextUriInfo.addResourcePart(complexResource);
          return null;
        }
      } else if (property instanceof EdmNavigationProperty) {
        // create navigation property
        UriResourceNavigationPropertyImpl navigationResource = new UriResourceNavigationPropertyImpl()
            .setNavigationProperty((EdmNavigationProperty) property);
        context.contextUriInfo.addResourcePart(navigationResource);
        return null;
      } else {
        throw wrap(new UriParserSemanticException("Unkown type for property '" + property + "'",
            UriParserSemanticException.MessageKeys.UNKNOWN_PROPERTY_TYPE, property.getName()));
      }

    } else { // with namespace

      FullQualifiedName fullFilterName = getFullNameFromContext(ctx.vNS, odi);

      // EdmType lastType = getLastType(lastTyped);
      if (source.type instanceof EdmEntityType) {

        EdmEntityType filterEntityType = edm.getEntityType(fullFilterName);
        if (filterEntityType != null) {
          // is entity type cast
          if (!(filterEntityType.compatibleTo(source.type))) {
            throw wrap(new UriParserSemanticException(
                "Entity typefilter not compatible to previous path segment: " + fullFilterName.toString(),
                UriParserSemanticException.MessageKeys.INCOMPATIBLE_TYPE_FILTER, fullFilterName.toString()));
          }

          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(source.isCollection);
            if (source.isCollection) {
              uriResource.setCollectionTypeFilter(filterEntityType);
            } else {
              uriResource.setEntryTypeFilter(filterEntityType);
            }
            context.contextUriInfo.addResourcePart(uriResource);
            return null;
          } else {

            // check if last segment may contain key properties
            if (lastResourcePart instanceof UriResourceWithKeysImpl) {
              UriResourceWithKeysImpl lastPartWithKeys = (UriResourceWithKeysImpl) lastResourcePart;

              if (lastPartWithKeys.isCollection() == false) {
                if (lastPartWithKeys.getTypeFilterOnEntry() != null) {
                  throw wrap(new UriParserSemanticException("Entry typefilters are not chainable, used '"
                      + getName(filterEntityType) + "' behind '"
                      + getName(lastPartWithKeys.getTypeFilterOnEntry()) + "'",
                      UriParserSemanticException.MessageKeys.TYPE_FILTER_NOT_CHAINABLE,
                      getName(lastPartWithKeys.getTypeFilterOnEntry()), getName(filterEntityType)));
                }
                lastPartWithKeys.setEntryTypeFilter(filterEntityType);
                return null;
              } else {
                if (lastPartWithKeys.getTypeFilterOnCollection() != null) {
                  throw wrap(new UriParserSemanticException("Collection typefilters are not chainable, used '"
                      + getName(filterEntityType) + "' behind '"
                      + getName(lastPartWithKeys.getTypeFilterOnCollection()) + "'",
                      UriParserSemanticException.MessageKeys.TYPE_FILTER_NOT_CHAINABLE,
                      getName(lastPartWithKeys.getTypeFilterOnCollection()), getName(filterEntityType)));
                }
                lastPartWithKeys.setCollectionTypeFilter(filterEntityType);
                return null;
              }
            } else if (lastResourcePart instanceof UriResourceTypedImpl) {
              UriResourceTypedImpl lastPartTyped = (UriResourceTypedImpl) lastResourcePart;
              if (lastPartTyped.getTypeFilter() != null) {
                throw wrap(new UriParserSemanticException("Typefilters are not chainable, used '"
                    + getName(filterEntityType) + "' behind '"
                    + getName(lastPartTyped.getTypeFilter()) + "'",
                    UriParserSemanticException.MessageKeys.TYPE_FILTER_NOT_CHAINABLE,
                    getName(lastPartTyped.getTypeFilter()), getName(filterEntityType)));
              }

              lastPartTyped.setTypeFilter(filterEntityType);
              return null;
            } else {
              throw wrap(new UriParserSemanticException("Path segment before '" + getName(filterEntityType)
                  + "' not typed",
                  UriParserSemanticException.MessageKeys.PREVIOUS_PART_NOT_TYPED, getName(filterEntityType)));
            }
          }
        }

      } else if (source.type instanceof EdmComplexType) {

        EdmComplexType filterComplexType = edm.getComplexType(fullFilterName);

        if (filterComplexType != null) {

          // is complex type cast
          if (!(filterComplexType.compatibleTo(source.type))) {
            throw wrap(new UriParserSemanticException(
                "Complex typefilter '" + getName(source.type) + "'not compatible type of previous path segment '"
                    + getName(filterComplexType) + "'",
                UriParserSemanticException.MessageKeys.INCOMPATIBLE_TYPE_FILTER, getName(source.type)));
          }

          // 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(source.isCollection);

            if (source.isCollection) {
              uriResource.setCollectionTypeFilter(filterComplexType);
            } else {
              uriResource.setEntryTypeFilter(filterComplexType);
            }
            context.contextUriInfo.addResourcePart(uriResource);
            return null;
          } else {
            if (lastResourcePart instanceof UriResourceWithKeysImpl) {
              // e.g. in case of function returning complex data or a list of complex data
              UriResourceWithKeysImpl lastPartWithKeys = (UriResourceWithKeysImpl) lastResourcePart;

              if (lastPartWithKeys.isCollection() == false) {
                if (lastPartWithKeys.getTypeFilterOnEntry() != null) {
                  throw wrap(new UriParserSemanticException("Entry typefilters are not chainable, used '"
                      + getName(filterComplexType) + "' behind '"
                      + getName(lastPartWithKeys.getTypeFilterOnEntry()) + "'",
                      UriParserSemanticException.MessageKeys.TYPE_FILTER_NOT_CHAINABLE,
                      getName(lastPartWithKeys.getTypeFilterOnEntry()), getName(filterComplexType)));
                }
                lastPartWithKeys.setEntryTypeFilter(filterComplexType);
                return null;
              } else {
                if (lastPartWithKeys.getTypeFilterOnCollection() != null) {
                  throw wrap(new UriParserSemanticException("Collection typefilters are not chainable, used '"
                      + getName(filterComplexType) + "' behind '"
                      + getName(lastPartWithKeys.getTypeFilterOnCollection()) + "'",
                      UriParserSemanticException.MessageKeys.TYPE_FILTER_NOT_CHAINABLE,
                      getName(lastPartWithKeys.getTypeFilterOnCollection()), getName(filterComplexType)));
                }
                lastPartWithKeys.setCollectionTypeFilter(filterComplexType);
                return null;
              }

            } else if (lastResourcePart instanceof UriResourceTypedImpl) {
              UriResourceTypedImpl lastPartTyped = (UriResourceTypedImpl) lastResourcePart;
              if (lastPartTyped.getTypeFilter() != null) {
                throw wrap(new UriParserSemanticException("Typefilters are not chainable, used '"
                    + getName(filterComplexType) + "' behind '"
                    + getName(lastPartTyped.getTypeFilter()) + "'",
                    UriParserSemanticException.MessageKeys.TYPE_FILTER_NOT_CHAINABLE,
                    getName(lastPartTyped.getTypeFilter()), getName(filterComplexType)));
              }

              lastPartTyped.setTypeFilter(filterComplexType);
              return null;
            } else {
              throw wrap(new UriParserSemanticException("Path segment before '" + getName(filterComplexType)
                  + "' not typed",
                  UriParserSemanticException.MessageKeys.PREVIOUS_PART_NOT_TYPED, getName(filterComplexType)));
            }
          }
        }
      }

      FullQualifiedName fullBindingTypeName = new FullQualifiedName(source.type.getNamespace(), source.type.getName());

      // check for action
      EdmAction action = edm.getBoundAction(fullFilterName, fullBindingTypeName, source.isCollection);
      if (action != null) {
        UriResourceActionImpl pathInfoAction = new UriResourceActionImpl();
        pathInfoAction.setAction(action);
        context.contextUriInfo.addResourcePart(pathInfoAction);
        return null;
      }

      // do a check for bound functions (which requires a parameter list)
      if (ctx.vlNVO.size() == 0) {
        throw wrap(new UriParserSemanticException("Expected function parameters for '" + fullBindingTypeName.toString()
            + "'",
            UriParserSemanticException.MessageKeys.FUNCTION_PARAMETERS_EXPECTED, fullBindingTypeName.toString()));
      }

      context.contextReadingFunctionParameters = true;
      @SuppressWarnings("unchecked")
      List<UriParameterImpl> parameters = (List<UriParameterImpl>) ctx.vlNVO.get(0).accept(this);
      context.contextReadingFunctionParameters = false;

      // get names of function parameters
      List<String> names = new ArrayList<String>();
      for (UriParameterImpl item : parameters) {
        names.add(item.getName());
      }

      EdmFunction function = edm.getBoundFunction(fullFilterName, fullBindingTypeName, source.isCollection, names);

      if (function != null) {
        UriResourceFunctionImpl pathInfoFunction = new UriResourceFunctionImpl()
            .setFunction(function)
            .setParameters(parameters);
        context.contextUriInfo.addResourcePart(pathInfoFunction);

        // mark parameters as consumed
        ctx.vlNVO.remove(0);
        return null;
      }

      // check for unbound function in the $filter case ( where the previous resource segment is a $it)
      function = edm.getUnboundFunction(fullFilterName, names);

      if (function != null) {
        UriResourceFunctionImpl pathInfoFunction = new UriResourceFunctionImpl()
            .setFunction(function)
            .setParameters(parameters);
        context.contextUriInfo.addResourcePart(pathInfoFunction);

        // mark parameters as consumed
        ctx.vlNVO.remove(0);
        return null;
      }

      throw wrap(new UriParserSemanticException("Unknown resource path segment:" + fullFilterName.toString(),
          UriParserSemanticException.MessageKeys.UNKNOWN_PART, fullFilterName.toString()));
    }
  }

  private String getName(final EdmType type) {
    return type.getFullQualifiedName().getFullQualifiedNameAsString();
  }

  @Override
  public Object visitAllEOF(final AllEOFContext ctx) {
    UriInfoImpl crossJoin = new UriInfoImpl().setKind(UriInfoKind.all);
    context.contextUriInfo = crossJoin;
    return null;
  }

  @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",
          UriParserSemanticException.MessageKeys.ONLY_FOR_TYPED_PARTS, "all"));
    }

    UriContext.LambdaVariables var = new UriContext.LambdaVariables();
    var.name = ctx.vLV.getText();
    var.type = getTypeInformation(obj).type;
    var.isCollection = false;

    all.setLamdaVariable(ctx.vLV.getText());
    context.allowedLambdaVariables.push(var);
    all.setExpression((ExpressionImpl) ctx.vLE.accept(this));
    context.allowedLambdaVariables.pop();
    return all;
  }

  @Override
  public ExpressionImpl visitAltAdd(final AltAddContext ctx) {
    BinaryImpl binary = new BinaryImpl();

    int tokenIndex = ctx.vO.getType();

    if (tokenIndex == UriLexer.ADD) {
      binary.setOperator(BinaryOperatorKind.ADD);
    } else if (tokenIndex == UriLexer.SUB) {
      binary.setOperator(BinaryOperatorKind.SUB);
    }

    binary.setLeftOperand((ExpressionImpl) ctx.vE1.accept(this));
    binary.setRightOperand((ExpressionImpl) ctx.vE2.accept(this));
    return binary;
  }

  @Override
  public Object visitAltAll(final AltAllContext ctx) {

    UriInfoImpl uriInfoImplpath = new UriInfoImpl().setKind(UriInfoKind.resource);

    uriInfoImplpath.addResourcePart((UriResourceImpl) super.visitAltAll(ctx));

    EdmType startType = removeUriResourceStartingTypeFilterImpl(uriInfoImplpath);

    MemberImpl ret = new MemberImpl();

    ret.setResourcePath(uriInfoImplpath);
    if (startType != null) {
      ret.setTypeFilter(startType);
    }

    return ret;
  }

  private EdmType removeUriResourceStartingTypeFilterImpl(final UriInfoImpl uriInfoImplpath) {

    List<UriResource> segments = uriInfoImplpath.getUriResourceParts();
    if (segments.size() == 0) {
      return null;
    }

    UriResource segment = segments.get(0);
    if (segment instanceof UriResourceStartingTypeFilterImpl) {
      UriResourceStartingTypeFilterImpl startingTypeFilter = (UriResourceStartingTypeFilterImpl) segment;

      EdmType type = null;
      if (startingTypeFilter.getTypeFilterOnEntry() != null) {
        type = startingTypeFilter.getTypeFilterOnEntry();
      } else if (startingTypeFilter.getTypeFilterOnCollection() != null) {
        type = startingTypeFilter.getTypeFilterOnCollection();
      } else {
        type = startingTypeFilter.getType();
      }

      uriInfoImplpath.removeResourcePart(0);
      return type;
    }

    return null;
  }

  @Override
  public ExpressionImpl visitAltAnd(final AltAndContext ctx) {
    BinaryImpl binary = new BinaryImpl();

    binary.setOperator(BinaryOperatorKind.AND);
    binary.setLeftOperand((ExpressionImpl) ctx.vE1.accept(this));
    binary.setRightOperand((ExpressionImpl) ctx.vE2.accept(this));

    return binary;
  }

  @Override
  public Object visitAltAny(final AltAnyContext ctx) {
    UriInfoImpl uriInfoImplpath = new UriInfoImpl().setKind(UriInfoKind.resource);

    uriInfoImplpath.addResourcePart((UriResourceImpl) super.visitAltAny(ctx));

    EdmType startType = removeUriResourceStartingTypeFilterImpl(uriInfoImplpath);

    MemberImpl ret = new MemberImpl();
    ret.setResourcePath(uriInfoImplpath);
    if (startType != null) {
      ret.setTypeFilter(startType);
    }
    return ret;
  }

  @Override
  public Object visitBatchEOF(final BatchEOFContext ctx) {
    context.contextUriInfo = new UriInfoImpl().setKind(UriInfoKind.batch);
    return null;
  }

  @Override
  public ExpressionImpl visitAltComparism(final AltComparismContext ctx) {
    BinaryImpl binary = new BinaryImpl();

    int tokenIndex = ctx.vO.getType();

    if (tokenIndex == UriLexer.GT) {
      binary.setOperator(BinaryOperatorKind.GT);
    } else if (tokenIndex == UriLexer.GE) {
      binary.setOperator(BinaryOperatorKind.GE);
    } else if (tokenIndex == UriLexer.LT) {
      binary.setOperator(BinaryOperatorKind.LT);
    } else if (tokenIndex == UriLexer.LE) {
      binary.setOperator(BinaryOperatorKind.LE);
    }

    binary.setLeftOperand((ExpressionImpl) ctx.vE1.accept(this));
    binary.setRightOperand((ExpressionImpl) ctx.vE2.accept(this));
    return binary;
  }

  @Override
  public Object visitEntityEOF(final EntityEOFContext ctx) {
    String odi = ctx.vODI.getText();
    FullQualifiedName fullName = getFullNameFromContext(ctx.vNS, odi);

    EdmEntityType type = edm.getEntityType(fullName);
    if (type == null) {
      throw wrap(new UriParserSemanticException("Expected EntityTypeName",
          UriParserSemanticException.MessageKeys.UNKNOWN_ENTITY_TYPE, fullName.toString()));
    }
    context.contextUriInfo.setEntityTypeCast(type);

    // contextUriInfo = uriInfo;
    context.contextTypes.push(new TypeInformation(context.contextUriInfo.getEntityTypeCast(), true));

    // @SuppressWarnings("unchecked")
    // List<QueryOptionImpl> list = (List<QueryOptionImpl>) ctx.vEO.accept(this);
    // uriInfo.setQueryOptions(list);
    return null;
  }

  @Override
  public ExpressionImpl visitAltEquality(final AltEqualityContext ctx) {
    BinaryImpl binary = new BinaryImpl();

    int tokenIndex = ctx.vO.getType();

    if (tokenIndex == UriLexer.EQ_ALPHA) {
      binary.setOperator(BinaryOperatorKind.EQ);
    } else {
      binary.setOperator(BinaryOperatorKind.NE);
    }
    binary.setLeftOperand((ExpressionImpl) ctx.vE1.accept(this));
    binary.setRightOperand((ExpressionImpl) ctx.vE2.accept(this));

    return binary;
  }

  @Override
  public Object visitAltHas(final AltHasContext ctx) {
    BinaryImpl binary = new BinaryImpl();

    binary.setOperator(BinaryOperatorKind.HAS);
    binary.setLeftOperand((ExpressionImpl) ctx.vE1.accept(this));
    binary.setRightOperand((ExpressionImpl) ctx.vE2.accept(this));

    return binary;
  }

  @Override
  public Object visitMetadataEOF(final MetadataEOFContext ctx) {
    UriInfoImpl uriInfo = new UriInfoImpl().setKind(UriInfoKind.metadata);

    context.contextUriInfo = uriInfo;
    return null;
  }

  @Override
  public ExpressionImpl visitAltMult(final AltMultContext ctx) {
    BinaryImpl binary = new BinaryImpl();

    int tokenIndex = ctx.vO.getType();

    if (tokenIndex == UriLexer.MUL) {
      binary.setOperator(BinaryOperatorKind.MUL);
    } else if (tokenIndex == UriLexer.DIV) {
      binary.setOperator(BinaryOperatorKind.DIV);
    } else {
      binary.setOperator(BinaryOperatorKind.MOD);
    }
    binary.setLeftOperand((ExpressionImpl) ctx.vE1.accept(this));
    binary.setRightOperand((ExpressionImpl) ctx.vE2.accept(this));

    return binary;
  }

  @Override
  public ExpressionImpl visitAltOr(final AltOrContext ctx) {
    BinaryImpl binary = new BinaryImpl();

    binary.setOperator(BinaryOperatorKind.OR);
    binary.setLeftOperand((ExpressionImpl) ctx.vE1.accept(this));
    binary.setRightOperand((ExpressionImpl) ctx.vE2.accept(this));

    return binary;
  }

  @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)) {
        throw wrap(new UriParserSemanticException("any only allowed on typed path segments",
            UriParserSemanticException.MessageKeys.ONLY_FOR_TYPED_PARTS, "any"));
      }

      UriContext.LambdaVariables var = new UriContext.LambdaVariables();
      var.name = ctx.vLV.getText();
      var.type = getTypeInformation(lastResourcePart).type;
      var.isCollection = false;

      any.setLamdaVariable(ctx.vLV.getText());
      context.allowedLambdaVariables.push(var);
      any.setExpression((ExpressionImpl) ctx.vLE.accept(this));
      context.allowedLambdaVariables.pop();
    }
    return any;
  }

  @Override
  public Object visitBooleanNonCase(final BooleanNonCaseContext ctx) {
    String text = ctx.getText().toLowerCase();

    if (text.equals("false")) {
      return new LiteralImpl().setText("false").setType(
          EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Boolean));
    }
    return new LiteralImpl().setText("true").setType(
        EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Boolean));
  }

  @Override
  public ExpressionImpl visitCastExpr(final CastExprContext ctx) {
    MethodImpl method = new MethodImpl();
    if (ctx.vE1 != null) {
      // is optional parameter
      ExpressionImpl onExpression = (ExpressionImpl) ctx.vE1.accept(this);
      method.addParameter(onExpression);
    }

    String namespace = ctx.vNS.getText();
    namespace = namespace.substring(0, namespace.length() - 1);

    FullQualifiedName fullName = new FullQualifiedName(namespace, ctx.vODI.getText());
    EdmType type = getType(fullName);
    method.setMethod(MethodKind.CAST);
    method.addParameter(new TypeLiteralImpl().setType(type));
    return method;
  }

  private EdmType getType(final FullQualifiedName fullName) {
    EdmType type = null;

    type = edm.getEntityType(fullName);
    if (type != null) {
      return type;
    }

    type = edm.getComplexType(fullName);
    if (type != null) {
      return type;
    }

    type = edm.getEnumType(fullName);
    if (type != null) {
      return type;
    }

    if (fullName.getNamespace().equals(EdmPrimitiveType.EDM_NAMESPACE)) {
      final EdmPrimitiveTypeKind typeKind = EdmPrimitiveTypeKind.valueOf(fullName.getName());
      type = EdmPrimitiveTypeFactory.getInstance(typeKind);
      if (type != null) {
        return type;
      }
    }

    return null;

  }

  @Override
  public ExpressionImpl visitCeilingMethodCallExpr(final CeilingMethodCallExprContext ctx) {
    return new MethodImpl()
        .setMethod(MethodKind.CEILING)
        .addParameter((ExpressionImpl) ctx.vE1.accept(this));
  }

  @Override
  public ExpressionImpl visitConcatMethodCallExpr(final ConcatMethodCallExprContext ctx) {
    return new MethodImpl()
        .setMethod(MethodKind.CONCAT)
        .addParameter((ExpressionImpl) ctx.vE1.accept(this))
        .addParameter((ExpressionImpl) ctx.vE2.accept(this));
  }

  @Override
  public Object visitConstSegment(final ConstSegmentContext ctx) {
    UriInfoImpl uriInfoResource = context.contextUriInfo;
    UriResource pathInfo = uriInfoResource.getLastResourcePart();

    if (ctx.vV != null) {
      if (pathInfo instanceof UriResourcePartTyped) {
        if (!((UriResourcePartTyped) pathInfo).isCollection()) {
          context.contextUriInfo.addResourcePart(new UriResourceValueImpl());
        } else {
          throw wrap(new UriParserSemanticException("$value only allowed on typed path segments",
              UriParserSemanticException.MessageKeys.ONLY_FOR_TYPED_PARTS, "$value"));
        }
        return null;
      } else {
        throw wrap(new UriParserSemanticException("$value only allowed on typed path segments",
            UriParserSemanticException.MessageKeys.ONLY_FOR_TYPED_PARTS, "$value"));
      }

    } else if (ctx.vC != null) {
      if (pathInfo instanceof UriResourcePartTyped) {
        if (((UriResourcePartTyped) pathInfo).isCollection()) {
          context.contextUriInfo.addResourcePart(new UriResourceCountImpl());
        } else {
          throw wrap(new UriParserSemanticException("$count only allowed on collection properties",
              UriParserSemanticException.MessageKeys.ONLY_FOR_COLLECTIONS, "$count"));
        }
      } else {
        throw wrap(new UriParserSemanticException("$count only allowed on typed properties",
            UriParserSemanticException.MessageKeys.ONLY_FOR_TYPED_PARTS, "$count"));
      }
    } else if (ctx.vR != null) {
      if (pathInfo instanceof UriResourcePartTyped) {
        EdmType type = ((UriResourcePartTyped) pathInfo).getType();
        if (type instanceof EdmEntityType) {
          context.contextUriInfo.addResourcePart(new UriResourceRefImpl());
        } else {
          throw wrap(new UriParserSemanticException("$ref only allowed on entity types",
              UriParserSemanticException.MessageKeys.ONLY_FOR_ENTITY_TYPES, "$ref"));
        }
      } else {
        throw wrap(new UriParserSemanticException("$ref only allowed on typed properties",
            UriParserSemanticException.MessageKeys.ONLY_FOR_TYPED_PROPERTIES, "$ref"));
      }

    } else if (ctx.vAll != null) {
      context.contextUriInfo.addResourcePart((UriResourceLambdaAllImpl) ctx.vAll.accept(this));
    } else if (ctx.vAny != null) {
      context.contextUriInfo.addResourcePart((UriResourceLambdaAnyImpl) ctx.vAny.accept(this));
    }
    return null;
  }

  @Override
  public ExpressionImpl visitContainsMethodCallExpr(final ContainsMethodCallExprContext ctx) {
    return new MethodImpl()
        .setMethod(MethodKind.CONTAINS)
        .addParameter((ExpressionImpl) ctx.vE1.accept(this))
        .addParameter((ExpressionImpl) ctx.vE2.accept(this));
  }

  @Override
  public Object visitCrossjoinEOF(final CrossjoinEOFContext ctx) {
    UriInfoImpl crossJoin = new UriInfoImpl().setKind(UriInfoKind.crossjoin);

    for (OdataIdentifierContext obj : ctx.vlODI) {
      crossJoin.addEntitySetName(obj.getText());
    }

    context.contextUriInfo = crossJoin;
    return null;
  }

  @Override
  public Object visitDateMethodCallExpr(final DateMethodCallExprContext ctx) {
    return new MethodImpl()
        .setMethod(MethodKind.DATE)
        .addParameter((ExpressionImpl) ctx.vE1.accept(this));
  }

  @Override
  public ExpressionImpl visitDayMethodCallExpr(final DayMethodCallExprContext ctx) {
    return new MethodImpl()
        .setMethod(MethodKind.DAY)
        .addParameter((ExpressionImpl) ctx.vE1.accept(this));
  }

  @Override
  public ExpressionImpl visitGeoDistanceMethodCallExpr(final GeoDistanceMethodCallExprContext ctx) {
    return new MethodImpl()
        .setMethod(MethodKind.GEODISTANCE)
        .addParameter((ExpressionImpl) ctx.vE1.accept(this))
        .addParameter((ExpressionImpl) ctx.vE2.accept(this));
  }

  @Override
  public Object visitEndsWithMethodCallExpr(final EndsWithMethodCallExprContext ctx) {
    return new MethodImpl()
        .setMethod(MethodKind.ENDSWITH)
        .addParameter((ExpressionImpl) ctx.vE1.accept(this))
        .addParameter((ExpressionImpl) ctx.vE2.accept(this));
  }

  @Override
  public Object visitEnumLit(final EnumLitContext ctx) {
    EnumerationImpl enum1 = new EnumerationImpl();

    // get type
    String odi = ctx.vODI.getText();

    FullQualifiedName fullName = getFullNameFromContext(ctx.vNS, odi);
    EdmEnumType edmEnumType = edm.getEnumType(fullName);

    enum1.setType(edmEnumType);

    String valueString = ctx.vValues.getText();
    valueString = valueString.substring(1, valueString.length() - 1);

    String[] values = valueString.split(",");
    for (String item : values) {
      enum1.addValue(item);
    }

    return enum1;
  }

  @Override
  public Object visitExpandItems(final ExpandItemsContext ctx) {
    ExpandOptionImpl expand = new ExpandOptionImpl();
    expand.setText(ctx.getText());
    for (ExpandItemContext eI : ctx.vlEI) {
      expand.addExpandItem((ExpandItemImpl) eI.accept(this));
    }

    return expand;
  }

  @Override
  public Object visitExpandItem(final ExpandItemContext ctx) {

    ExpandItemImpl expandItem = null;
    if (ctx.vS != null) {
      expandItem = new ExpandItemImpl().setIsStar(true);
      if (ctx.vR != null) {
        expandItem.setIsRef(true);
      } else if (ctx.vM != null) {
        LevelsOptionImpl levels = new LevelsOptionImpl().setMax();
        levels.setText(ctx.vM.getText());
        expandItem.setSystemQueryOption(levels);
      } else if (ctx.vL != null) {
        LevelsOptionImpl levels = new LevelsOptionImpl();
        String text = ctx.vL.getText();
        levels.setText(text);
        levels.setValue(Integer.parseInt(text));
        expandItem.setSystemQueryOption(levels);
      }

    } else if (ctx.vEP != null) {
      expandItem = (ExpandItemImpl) ctx.vEP.accept(this);

      if (ctx.vEPE != null) {
        ExpandItemImpl contextExpandItemPathBU = context.contextExpandItemPath;
        context.contextExpandItemPath = expandItem;

        @SuppressWarnings("unchecked")
        List<SystemQueryOptionImpl> list = (List<SystemQueryOptionImpl>) ctx.vEPE.accept(this);
        for (SystemQueryOptionImpl option : list) {
          expandItem.setSystemQueryOption(option);
        }
        context.contextExpandItemPath = contextExpandItemPathBU;
      }
    }

    return expandItem;

  }

  @Override
  public Object visitExpandPath(final ExpandPathContext ctx) {
    ExpandItemImpl expandItem = new ExpandItemImpl();

    // UriResourceItImpl pathInfoIT = new UriResourceItImpl();
    context.contextUriInfo.getLastResourcePart();

    // save context
    ExpandItemImpl contextExpandItemPathBU = context.contextExpandItemPath;
    UriInfoImpl uriInfoResourceBU = context.contextUriInfo;

    // set tmp context
    context.contextExpandItemPath = expandItem;
    context.contextUriInfo = new UriInfoImpl().setKind(UriInfoKind.resource);
    // contextUriInfo.addPathInfo(pathInfoIT);

    super.visitExpandPath(ctx);

    EdmType startType = removeUriResourceStartingTypeFilterImpl(context.contextUriInfo);
    expandItem.setResourcePath(context.contextUriInfo);
    if (startType != null) {
      expandItem.setTypeFilter(startType);
    }

    // reset context
    context.contextUriInfo = uriInfoResourceBU;
    context.contextExpandItemPath = contextExpandItemPathBU;

    return expandItem;
  }

  @Override
  public Object visitExpandPathExtension(final ExpandPathExtensionContext ctx) {
    List<SystemQueryOptionImpl> list = new ArrayList<SystemQueryOptionImpl>();

    EdmType targetType = null;
    boolean isColl = false;
    if (context.contextExpandItemPath == null) {
      // use the type of the last resource path segement
      UriResourceTypedImpl lastSegment = (UriResourceTypedImpl) context.contextUriInfo.getLastResourcePart();
      targetType = getTypeInformation(lastSegment).type;
      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 = getTypeInformation(lastSegment).type;
        isColl = lastSegment.isCollection();
      } else {
        // use the type of the last ''expand'' path segement
        UriInfoImpl info = (UriInfoImpl) context.contextExpandItemPath.getResourcePath();
        targetType = getTypeInformation(info.getLastResourcePart()).type;
        isColl = ((UriResourcePartTyped) info.getLastResourcePart()).isCollection();
      }
    }

    context.contextTypes.push(new TypeInformation(targetType, isColl));

    if (ctx.vC != null) {
      UriInfoImpl resourcePath = (UriInfoImpl) context.contextExpandItemPath.getResourcePath();
      resourcePath.addResourcePart(new UriResourceCountImpl());

      for (ExpandCountOptionContext s : ctx.vlEOC) {
        list.add((SystemQueryOptionImpl) s.accept(this));
      }
    } else if (ctx.vR != null) {
      UriInfoImpl resourcePath = (UriInfoImpl) context.contextExpandItemPath.getResourcePath();
      resourcePath.addResourcePart(new UriResourceRefImpl());

      for (ExpandRefOptionContext s : ctx.vlEOR) {
        list.add((SystemQueryOptionImpl) s.accept(this));
      }
    } else {
      for (ExpandOptionContext s : ctx.vlEO) {
        list.add((SystemQueryOptionImpl) s.accept(this));
      }
    }

    context.contextTypes.pop();
    return list;

  }

  @Override
  public Object visitFilter(final FilterContext ctx) {

    FilterOptionImpl filter = new FilterOptionImpl().setExpression((ExpressionImpl) ctx.children.get(2).accept(this));
    return filter;
  }

  @Override
  public Object visitFilterExpressionEOF(final FilterExpressionEOFContext ctx) {

    FilterOptionImpl filter = new FilterOptionImpl().setExpression((ExpressionImpl) ctx.children.get(0).accept(this));
    return filter;
  }

  @Override
  public ExpressionImpl visitFloorMethodCallExpr(final FloorMethodCallExprContext ctx) {
    return new MethodImpl()
        .setMethod(MethodKind.FLOOR)
        .addParameter((ExpressionImpl) ctx.vE1.accept(this));
  }

  @Override
  public ExpressionImpl visitFractionalsecondsMethodCallExpr(final FractionalsecondsMethodCallExprContext ctx) {
    return new MethodImpl()
        .setMethod(MethodKind.FRACTIONALSECONDS)
        .addParameter((ExpressionImpl) ctx.vE1.accept(this));
  }

  @Override
  public ExpressionImpl visitGeoLengthMethodCallExpr(final GeoLengthMethodCallExprContext ctx) {
    return new MethodImpl()
        .setMethod(MethodKind.GEOLENGTH)
        .addParameter((ExpressionImpl) ctx.vE1.accept(this));
  }

  @Override
  public ExpressionImpl visitHourMethodCallExpr(final HourMethodCallExprContext ctx) {
    return new MethodImpl()
        .setMethod(MethodKind.HOUR)
        .addParameter((ExpressionImpl) ctx.vE1.accept(this));
  }

  @Override
  public ExpressionImpl visitIndexOfMethodCallExpr(final IndexOfMethodCallExprContext ctx) {
    return new MethodImpl()
        .setMethod(MethodKind.INDEXOF)
        .addParameter((ExpressionImpl) ctx.vE1.accept(this))
        .addParameter((ExpressionImpl) ctx.vE2.accept(this));
  }

  @Override
  public Object visitInlinecount(final InlinecountContext ctx) {
    CountOptionImpl inlineCount = new CountOptionImpl();

    String text = ctx.children.get(2).getText();

    return inlineCount.setValue(text.toLowerCase().equals("true") ? true : false).setText(text);
  }

  @Override
  public ExpressionImpl visitGeoIntersectsMethodCallExpr(final GeoIntersectsMethodCallExprContext ctx) {
    return new MethodImpl()
        .setMethod(MethodKind.GEOINTERSECTS)
        .addParameter((ExpressionImpl) ctx.vE1.accept(this))
        .addParameter((ExpressionImpl) ctx.vE2.accept(this));
  }

  @Override
  public ExpressionImpl visitIsofExpr(final IsofExprContext ctx) {
    MethodImpl method = new MethodImpl();
    if (ctx.vE1 != null) {
      ExpressionImpl onExpression = (ExpressionImpl) ctx.vE1.accept(this);
      method.addParameter(onExpression);
    }

    String namespace = ctx.vNS.getText();
    namespace = namespace.substring(0, namespace.length() - 1);

    FullQualifiedName fullName = new FullQualifiedName(namespace, ctx.vODI.getText());
    EdmType type = getType(fullName);
    method.setMethod(MethodKind.ISOF);
    method.addParameter(new TypeLiteralImpl().setType(type));

    return method;
  }

  @Override
  public ExpressionImpl visitLengthMethodCallExpr(final LengthMethodCallExprContext ctx) {
    return new MethodImpl()
        .setMethod(MethodKind.LENGTH)
        .addParameter((ExpressionImpl) ctx.vE1.accept(this));
  }

  @Override
  public Object visitLevels(final LevelsContext ctx) {

    LevelsOptionImpl levels = new LevelsOptionImpl();

    String text = ctx.children.get(2).getText();

    if (text.equals("max")) {
      levels.setMax();
    } else {
      levels.setValue(Integer.parseInt(text));
    }
    levels.setText(text);

    return levels;

  }

  @Override
  public ExpressionImpl visitMaxDateTimeMethodCallExpr(final MaxDateTimeMethodCallExprContext ctx) {
    return new MethodImpl()
        .setMethod(MethodKind.MAXDATETIME);
  }

  @Override
  public Object visitMemberExpr(final MemberExprContext ctx) {

    UriInfoImpl uriInfoImplpath = new UriInfoImpl().setKind(UriInfoKind.resource);

    if (context.contextTypes.isEmpty()) {
      throw wrap(new UriParserSemanticException("Expression '" + ctx.getText() + "' is not allowed as key value.",
          UriParserSemanticException.MessageKeys.INVALID_KEY_VALUE, ctx.getText()));
    }
    TypeInformation lastTypeInfo = context.contextTypes.peek();

    if (ctx.vIt != null || ctx.vIts != null) {
      UriResourceItImpl pathInfoIT = new UriResourceItImpl();
      pathInfoIT.setType(lastTypeInfo.type);
      pathInfoIT.setCollection(lastTypeInfo.isCollection);
      uriInfoImplpath.addResourcePart(pathInfoIT);
    }

    if (ctx.vPs != null) {
      // save the context
      UriInfoImpl backupUriInfoPath = context.contextUriInfo;

      // set temporary uriInfoPath
      context.contextUriInfo = uriInfoImplpath;

      ctx.vPs.accept(this);

      // reset context
      context.contextUriInfo = backupUriInfoPath;
    }

    if (ctx.vALL != null) {
      uriInfoImplpath.addResourcePart((UriResourceImpl) ctx.vALL.accept(this));
    }
    if (ctx.vANY != null) {
      uriInfoImplpath.addResourcePart((UriResourceImpl) ctx.vANY.accept(this));
    }

    EdmType startType = removeUriResourceStartingTypeFilterImpl(uriInfoImplpath);

    MemberImpl ret = new MemberImpl();
    ret.setResourcePath(uriInfoImplpath);
    if (startType != null) {
      ret.setTypeFilter(startType);
    }

    return ret;
  }

  @Override
  public ExpressionImpl visitMinDateTimeMethodCallExpr(final MinDateTimeMethodCallExprContext ctx) {
    return new MethodImpl()
        .setMethod(MethodKind.MINDATETIME);
  }

  @Override
  public ExpressionImpl visitMinuteMethodCallExpr(final MinuteMethodCallExprContext ctx) {
    return new MethodImpl()
        .setMethod(MethodKind.MINUTE)
        .addParameter((ExpressionImpl) ctx.vE1.accept(this));
  }

  @Override
  public ExpressionImpl visitMonthMethodCallExpr(final MonthMethodCallExprContext ctx) {
    return new MethodImpl()
        .setMethod(MethodKind.MONTH)
        .addParameter((ExpressionImpl) ctx.vE1.accept(this));
  }

  @Override
  public Object visitNameValueOptList(final NameValueOptListContext ctx) {
    if (ctx.vVO != null) {

      // is single key predicate without a name
      String valueText = ctx.vVO.getText();
      ExpressionImpl expression = null;
      try {
        expression = (ExpressionImpl) ctx.vVO.accept(this);
      } catch (final RuntimeException e) {
        throw wrap(new UriParserSemanticException("Invalid key value: " + valueText, e,
            UriParserSemanticException.MessageKeys.INVALID_KEY_VALUE, valueText));
      }

      // get type of last resource part
      UriResource last = context.contextUriInfo.getLastResourcePart();
      if (!(last instanceof UriResourcePartTyped)) {
        throw wrap(new UriParserSemanticException("Parameters list on untyped resource path segment not allowed",
            UriParserSemanticException.MessageKeys.PARAMETERS_LIST_ONLY_FOR_TYPED_PARTS));
      }
      EdmEntityType lastType = (EdmEntityType) ((UriResourcePartTyped) last).getType();

      // get list of keys for lastType
      List<String> lastKeyPredicates = lastType.getKeyPredicateNames();

      // If there is exactly one key defined in the EDM, then this key is the key written in the URI,
      // so fill the keylist with this key and return.
      if (lastKeyPredicates.size() == 1) {
        return Collections.singletonList(new UriParameterImpl()
            .setName(lastKeyPredicates.get(0))
            .setText(valueText)
            .setExpression(expression));
      }

      // There are more keys defined in the EDM, but only one is written in the URI. This is allowed only if
      // referential constraints are defined on this navigation property which can be used to fill up all
      // required keys.
      // For using referential constraints the last resource part must be a navigation property.
      if (!(context.contextUriInfo.getLastResourcePart() instanceof UriResourceNavigationPropertyImpl)) {
        throw wrap(new UriParserSemanticException("Wrong number of key properties.",
            UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES,
            Integer.toString(lastKeyPredicates.size()), "1"));
      }
      UriResourceNavigationPropertyImpl lastNav = (UriResourceNavigationPropertyImpl) last;

      // get the partner of the navigation property
      EdmNavigationProperty partner = lastNav.getProperty().getPartner();
      if (partner == null) {
        throw wrap(new UriParserSemanticException("Wrong number of key properties.",
            UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES,
            Integer.toString(lastKeyPredicates.size()), "1"));
      }

      // create the keylist
      List<UriParameterImpl> list = new ArrayList<UriParameterImpl>();

      // Find the keys not filled by referential constraints
      // and collect the other keys filled by referential constraints.
      String missedKey = null;
      for (String item : lastKeyPredicates) {
        String property = partner.getReferencingPropertyName(item);
        if (property != null) {
          list.add(new UriParameterImpl().setName(item).setRefencedProperty(property));
        } else {
          if (missedKey == null) {
            missedKey = item;
          } else {
            // two of more keys are missing
            throw wrap(new UriParserSemanticException("Not enough referential constraints defined",
                UriParserSemanticException.MessageKeys.NOT_ENOUGH_REFERENTIAL_CONSTRAINTS));
          }
        }
      }

      // the missing key is the one which is defined in the URI
      list.add(new UriParameterImpl().setName(missedKey).setText(valueText).setExpression(expression));

      return list;
    } else if (ctx.vNVL != null) {

      List<UriParameterImpl> list = new ArrayList<UriParameterImpl>();

      for (ParseTree c : ctx.vNVL.vlNVP) {
        list.add((UriParameterImpl) c.accept(this));
      }

      if (context.contextReadingFunctionParameters) {
        return list;
      }

      UriResource last = context.contextUriInfo.getLastResourcePart();
      // if the last resource part is a function
      /*
       * if (last instanceof UriResourceFunctionImpl) {
       * UriResourceFunctionImpl function = (UriResourceFunctionImpl) last;
       * if (!function.isParameterListFilled()) {
       * return list;
       * }
       * }
       */

      // get type of last resource part
      if (!(last instanceof UriResourcePartTyped)) {
        throw wrap(new UriParserSemanticException("Parameters list on untyped resource path segment not allowed",
            UriParserSemanticException.MessageKeys.PARAMETERS_LIST_ONLY_FOR_TYPED_PARTS));
      }
      EdmEntityType lastType = (EdmEntityType) ((UriResourcePartTyped) last).getType();

      // get list of keys for lastType
      List<String> lastKeyPredicates = lastType.getKeyPredicateNames();

      // check if all key are filled from the URI
      if (list.size() == lastKeyPredicates.size()) {
        return list;
      }

      // if not, check if the missing key predicates can be satisfied with help of the defined
      // referential constraints
      // for using referential constraints the last resource part must be a navigation property
      if (!(context.contextUriInfo.getLastResourcePart() instanceof UriResourceNavigationPropertyImpl)) {
        throw wrap(new UriParserSemanticException("Wrong number of key properties.",
            UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES,
            Integer.toString(lastKeyPredicates.size()), Integer.toString(list.size())));
      }
      UriResourceNavigationPropertyImpl lastNav = (UriResourceNavigationPropertyImpl) last;

      // get the partner of the navigation property
      EdmNavigationProperty partner = lastNav.getProperty().getPartner();
      if (partner == null) {
        throw wrap(new UriParserSemanticException("Wrong number of key properties.",
            UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES,
            Integer.toString(lastKeyPredicates.size()), Integer.toString(list.size())));
      }

      // fill missing keys from referential constraints
      for (String key : lastKeyPredicates) {
        boolean found = false;
        for (UriParameterImpl item : list) {
          if (item.getName().equals(key)) {
            found = true;
            break;
          }
        }

        if (!found) {
          String property = partner.getReferencingPropertyName(key);
          if (property != null) {
            // store the key name as referenced property
            list.add(0, new UriParameterImpl().setName(key).setRefencedProperty(property));
          }
        }
      }

      // check again if all key predicates are filled from the URI
      if (list.size() == lastKeyPredicates.size()) {
        return list;
      } else {
        throw wrap(new UriParserSemanticException("Wrong number of key properties.",
            UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES,
            Integer.toString(lastKeyPredicates.size()), Integer.toString(list.size())));
      }
    } else {
      if (context.contextReadingFunctionParameters) {
        return Collections.emptyList();
      } else {
        final UriResource last = context.contextUriInfo.getLastResourcePart();
        final int number = last instanceof UriResourcePartTyped ?
            ((EdmEntityType) ((UriResourcePartTyped) last).getType()).getKeyPredicateNames().size() : 0;
        throw wrap(new UriParserSemanticException("Wrong number of key properties.",
            UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES, Integer.toString(number), "0"));
      }
    }
  }

  @Override
  public UriParameterImpl visitNameValuePair(final NameValuePairContext ctx) {
    UriParameterImpl uriParameter = new UriParameterImpl();
    uriParameter.setName(ctx.vODI.getText());

    if (ctx.vCOM != null) {
      uriParameter.setText(ctx.vCOM.getText());
      uriParameter.setExpression((ExpressionImpl) ctx.vCOM.accept(this));
    } else {
      uriParameter.setAlias("@" + ctx.vALI.getText());
    }

    return uriParameter;
  }

  @Override
  public Object visitNaninfinity(final NaninfinityContext ctx) {
    return new LiteralImpl().setType(EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Decimal)).
        setText(ctx.getText());
  }

  @Override
  public ExpressionImpl visitNowMethodCallExpr(final NowMethodCallExprContext ctx) {
    return new MethodImpl()
        .setMethod(MethodKind.NOW);
  }

  @Override
  public Object visitNullrule(final NullruleContext ctx) {
    return new LiteralImpl().setText("null");
  }

  /*
   * @Override
   * public Object visitOdataRelativeUriEOF(final OdataRelativeUriEOFContext ctx) {
   * contextUriInfo = null;
   * super.visitOdataRelativeUriEOF(ctx);
   * return contextUriInfo;
   * }
   */
  @Override
  public Object visitOrderBy(final OrderByContext ctx) {

    OrderByOptionImpl orderBy = new OrderByOptionImpl();

    for (OrderByItemContext item : ((OrderListContext) ctx.getChild(2)).vlOI) {
      OrderByItemImpl oItem = (OrderByItemImpl) item.accept(this);
      orderBy.addOrder(oItem);
    }

    return orderBy;
  }

  @Override
  public Object visitOrderByEOF(final OrderByEOFContext ctx) {

    OrderByOptionImpl orderBy = new OrderByOptionImpl();

    for (OrderByItemContext item : ((OrderListContext) ctx.getChild(0)).vlOI) {
      OrderByItemImpl oItem = (OrderByItemImpl) item.accept(this);
      orderBy.addOrder(oItem);
    }

    return orderBy;
  }

  @Override
  public Object visitOrderByItem(final OrderByItemContext ctx) {
    OrderByItemImpl oItem = new OrderByItemImpl();
    if (ctx.vD != null) {
      oItem.setDescending(true);
    }

    oItem.setExpression((ExpressionImpl) ctx.vC.accept(this));
    return oItem;
  }

  @Override
  public Object visitPathSegment(final PathSegmentContext ctx) {
    readResourcePathSegment(ctx);
    /*
     * if (contextUriInfo.getLastResourcePart() == null ||
     * contextUriInfo.getLastResourcePart() instanceof UriResourceRootImpl) {
     * 
     * } else {
     * readNextPathInfoSegment(ctx);
     * }
     */
    UriResourceImpl pathInfoSegment = (UriResourceImpl) context.contextUriInfo.getLastResourcePart();

    if (ctx.vlNVO.size() > 0) {
      // check for keyPredicates
      if (pathInfoSegment instanceof UriResourceWithKeysImpl) {
        @SuppressWarnings("unchecked")
        List<UriParameterImpl> list = (List<UriParameterImpl>) ctx.vlNVO.get(0).accept(this);
        ((UriResourceWithKeysImpl) pathInfoSegment)
            .setKeyPredicates(list);
      } else {
        throw wrap(new UriParserSemanticException("Key properties not allowed",
            UriParserSemanticException.MessageKeys.KEY_NOT_ALLOWED));
      }
    }

    return pathInfoSegment;
  }

  @Override
  public Object visitPathSegments(final PathSegmentsContext ctx) {
    // path segment
    for (PathSegmentContext it : ctx.vlPS) {
      it.accept(this);
    }

    // const segment
    if (ctx.vCS != null) {
      ctx.vCS.accept(this);
    }
    return null;
  }

  @Override
  public Object visitPrimitiveLiteral(final PrimitiveLiteralContext ctx) {
    ParseTree child1 = ctx.children.get(0);

    if (child1 instanceof EnumLitContext
        || child1 instanceof BooleanNonCaseContext
        || child1 instanceof NullruleContext
        || child1 instanceof NaninfinityContext) {
      return child1.accept(this);
    }
    return new LiteralImpl().setText(ctx.getText());
  }

  @Override
  public Object visitQueryOptions(final QueryOptionsContext ctx) {

    List<QueryOptionImpl> qpList = new ArrayList<QueryOptionImpl>();
    for (QueryOptionContext entityOption : ctx.vlQO) {
      qpList.add((QueryOptionImpl) entityOption.accept(this));
    }

    return qpList;
  }

  /*
   * @Override
   * public Object visitResourcePath(final ResourcePathContext ctx) {
   * if (ctx.vAll != null) {
   * contextUriInfo = new UriInfoImpl().setKind(UriInfoKind.all);
   * } else if (ctx.vCJ != null) {
   * ctx.vCJ.accept(this);
   * } else if (ctx.vlPS != null) {
   * UriInfoImpl uriInfoPath = new UriInfoImpl().setKind(UriInfoKind.resource);
   * contextUriInfo = uriInfoPath;
   * super.visitResourcePath(ctx); // visit all children of ctx
   * }
   * return contextUriInfo;
   * }
   */
  @Override
  public Object visitRootExpr(final RootExprContext ctx) {

    UriResource lastResource = context.contextUriInfo.getLastResourcePart();

    if (!(lastResource instanceof UriResourcePartTyped)) {
      throw wrap(new UriParserSemanticException("Resource path not typed",
          UriParserSemanticException.MessageKeys.RESOURCE_PATH_NOT_TYPED));
    }

    UriResourcePartTyped lastType = (UriResourcePartTyped) lastResource;

    UriResourceRootImpl pathInfoRoot = new UriResourceRootImpl();
    pathInfoRoot.setCollection(lastType.isCollection());
    pathInfoRoot.setType(getTypeInformation(lastType).type);

    UriInfoImpl uriInfoImplpath = new UriInfoImpl().setKind(UriInfoKind.resource);
    uriInfoImplpath.addResourcePart(pathInfoRoot);

    if (ctx.vPs != null) {
      // store the context uriInfoPath
      UriInfoImpl backupUriInfoPath = context.contextUriInfo;

      // set temporary uriInfoPath to collect the path information of the memberExpression
      context.contextUriInfo = uriInfoImplpath;

      ctx.vPs.accept(this);

      context.contextUriInfo = backupUriInfoPath;

    }
    return new MemberImpl()
        .setResourcePath(uriInfoImplpath);

  }

  @Override
  public ExpressionImpl visitRoundMethodCallExpr(final RoundMethodCallExprContext ctx) {
    return new MethodImpl()
        .setMethod(MethodKind.ROUND)
        .addParameter((ExpressionImpl) ctx.vE1.accept(this));
  }

  @Override
  public ExpressionImpl visitSecondMethodCallExpr(final SecondMethodCallExprContext ctx) {
    return new MethodImpl()
        .setMethod(MethodKind.SECOND)
        .addParameter((ExpressionImpl) ctx.vE1.accept(this));
  }

  @Override
  public Object visitSelect(final SelectContext ctx) {
    List<SelectItemImpl> selectItems = new ArrayList<SelectItemImpl>();

    for (SelectItemContext si : ctx.vlSI) {
      selectItems.add((SelectItemImpl) si.accept(this));
    }

    return new SelectOptionImpl().setSelectItems(selectItems).setText(ctx.children.get(2).getText());
  }

  @Override
  public Object visitSelectEOF(final SelectEOFContext ctx) {
    List<SelectItemImpl> selectItems = new ArrayList<SelectItemImpl>();

    for (SelectItemContext si : ctx.vlSI) {
      selectItems.add((SelectItemImpl) si.accept(this));
    }

    return new SelectOptionImpl().setSelectItems(selectItems).setText(ctx.getText());
  }

  @Override
  public Object visitSelectItem(final SelectItemContext ctx) {
    SelectItemImpl selectItem = new SelectItemImpl();

    context.contextSelectItem = selectItem;
    for (SelectSegmentContext si : ctx.vlSS) {
      si.accept(this);
    }
    context.contextSelectItem = null;

    return selectItem;
  }

  @Override
  public Object visitSelectSegment(final SelectSegmentContext ctx) {

    if (ctx.vS != null) {
      if (ctx.vNS != null) {
        String namespace = ctx.vNS.getText();
        namespace = namespace.substring(0, namespace.length() - 1);
        FullQualifiedName fullName = new FullQualifiedName(namespace, "*");
        context.contextSelectItem.addAllOperationsInSchema(fullName);
      } else {
        context.contextSelectItem.setStar(true);
      }
      return null;
    }

    String odi = ctx.vODI.getText();
    if (ctx.vNS == null) {

      EdmType prevType = null;
      if (context.contextSelectItem.getResourcePath() == null) {
        prevType = context.contextTypes.peek().type;
      } else {
        UriInfoImpl uriInfo = (UriInfoImpl) context.contextSelectItem.getResourcePath();
        UriResource last = uriInfo.getLastResourcePart();

        prevType = getTypeInformation(last).type;
        if (prevType == null) {
          throw wrap(new UriParserSemanticException("prev segment not typed",
              UriParserSemanticException.MessageKeys.ONLY_FOR_TYPED_PARTS, "select"));
        }
      }

      if (!(prevType instanceof EdmStructuredType)) {
        throw wrap(new UriParserSemanticException("Previous select item is not a structural type",
            UriParserSemanticException.MessageKeys.ONLY_FOR_STRUCTURAL_TYPES, "select"));
      }

      EdmStructuredType structType = (EdmStructuredType) prevType;
      EdmElement element = structType.getProperty(odi);
      if (element == null) {
        throw wrap(new UriParserSemanticException("Previous select item has not property: " + odi,
            UriParserSemanticException.MessageKeys.EXPRESSION_PROPERTY_NOT_IN_TYPE, structType.getName(), odi));
      }

      // create new segment
      // SelectSegmentImpl newSegment = new SelectSegmentImpl().setProperty(property);
      // contextSelectItem.addSegment(newSegment);
      if (element instanceof EdmProperty) {
        EdmProperty property = (EdmProperty) element;
        if (property.isPrimitive()) {

          UriResourcePrimitivePropertyImpl simple = new UriResourcePrimitivePropertyImpl();
          simple.setProperty(property);

          UriInfoImpl uriInfo = (UriInfoImpl) context.contextSelectItem.getResourcePath();
          if (uriInfo == null) {
            uriInfo = new UriInfoImpl().setKind(UriInfoKind.resource);
            uriInfo.addResourcePart(simple);

            EdmType startType = removeUriResourceStartingTypeFilterImpl(uriInfo);
            if (startType != null) {
              context.contextSelectItem.setTypeFilter(startType);
            }

            context.contextSelectItem.setResourcePath(uriInfo);
          } else {
            uriInfo.addResourcePart(simple);
          }
          return this;
        } else {
          UriInfoImpl uriInfo = (UriInfoImpl) context.contextSelectItem.getResourcePath();

          UriResourceComplexPropertyImpl complex = new UriResourceComplexPropertyImpl();
          complex.setProperty(property);

          if (uriInfo == null) {
            uriInfo = new UriInfoImpl().setKind(UriInfoKind.resource);
            uriInfo.addResourcePart(complex);

            EdmType startType = removeUriResourceStartingTypeFilterImpl(uriInfo);
            if (startType != null) {
              context.contextSelectItem.setTypeFilter(startType);
            }

            context.contextSelectItem.setResourcePath(uriInfo);
          } else {
            uriInfo.addResourcePart(complex);
          }
          return this;
        }
      } else {
        throw wrap(new UriParserSemanticException("Only Simple and Complex properties within select allowed",
            UriParserSemanticException.MessageKeys.ONLY_SIMPLE_AND_COMPLEX_PROPERTIES_IN_SELECT));
      }
    } else {
      String namespace = ctx.vNS.getText();
      namespace = namespace.substring(0, namespace.length() - 1);

      FullQualifiedName fullName = new FullQualifiedName(namespace, odi);
      // contextSelectItem.addQualifiedThing(fullName);

      if (context.contextSelectItem.getResourcePath() == null) {
        EdmType prevType = context.contextTypes.peek().type;

        // check for complex type cast
        if (prevType instanceof EdmComplexType) {
          EdmComplexType ct = edm.getComplexType(fullName);
          if (ct != null) {
            if ((ct.compatibleTo(prevType))) {
              UriResourceStartingTypeFilterImpl resourcePart = new UriResourceStartingTypeFilterImpl();
              resourcePart.setCollectionTypeFilter(ct);

              UriInfoImpl uriInfo = new UriInfoImpl().setKind(UriInfoKind.resource);
              uriInfo.addResourcePart(resourcePart);

              EdmType startType = removeUriResourceStartingTypeFilterImpl(uriInfo);
              if (startType != null) {
                context.contextSelectItem.setTypeFilter(startType);
              }

              context.contextSelectItem.setResourcePath(uriInfo);
              return this;
            }
          }
        } else if (prevType instanceof EdmEntityType) {
          EdmEntityType et = edm.getEntityType(fullName);
          if (et != null) {
            if ((et.compatibleTo(prevType))) {
              UriResourceStartingTypeFilterImpl resourcePart = new UriResourceStartingTypeFilterImpl();
              resourcePart.setCollectionTypeFilter(et);

              UriInfoImpl uriInfo = new UriInfoImpl().setKind(UriInfoKind.resource);
              uriInfo.addResourcePart(resourcePart);

              EdmType startType = removeUriResourceStartingTypeFilterImpl(uriInfo);
              if (startType != null) {
                context.contextSelectItem.setTypeFilter(startType);
              }

              context.contextSelectItem.setResourcePath(uriInfo);
              return this;
            }
          }
        } else {
          throw wrap(new UriParserSemanticException("prev segment must be complex of entity type",
              UriParserSemanticException.MessageKeys.COMPLEX_PROPERTY_OF_ENTITY_TYPE_EXPECTED));
        }

      } else {
        UriInfoImpl uriInfo = (UriInfoImpl) context.contextSelectItem.getResourcePath();
        UriResource last = uriInfo.getLastResourcePart();
        if (!(last instanceof UriResourceTypedImpl)) {
          throw wrap(new UriParserSemanticException("prev segment typed",
              UriParserSemanticException.MessageKeys.ONLY_FOR_TYPED_PARTS, "select"));
        }
        EdmType prevType = getTypeInformation(last).type;

        if (prevType instanceof EdmComplexType) {
          EdmComplexType ct = edm.getComplexType(fullName);
          if (ct != null) {
            if ((ct.compatibleTo(prevType))) {
              UriResourceStartingTypeFilterImpl resourcePart = new UriResourceStartingTypeFilterImpl();
              resourcePart.setCollectionTypeFilter(ct);

              uriInfo.addResourcePart(resourcePart);
              return this;
            }
          }
        } else if (prevType instanceof EdmEntityType) {
          throw wrap(new UriParserSemanticException("Error",
              UriParserSemanticException.MessageKeys.NOT_FOR_ENTITY_TYPE));
          /*
           * EdmEntityType et = edm.getEntityType(fullName);
           * if (et != null) {
           * if ((et.compatibleTo((EdmStructuralType) prevType))) {
           * UriResourceStartingTypeFilterImpl resourcePart = new UriResourceStartingTypeFilterImpl();
           * resourcePart.setEntryTypeFilter(et);
           * 
           * uriInfo.addResourcePart(resourcePart);
           * return this;
           * }
           * }
           */
        } else {
          throw wrap(new UriParserSemanticException("prev segment must be complex of entity type",
              UriParserSemanticException.MessageKeys.COMPLEX_PROPERTY_OF_ENTITY_TYPE_EXPECTED));
        }
      }

      EdmType prevType = null;
      if (context.contextSelectItem.getResourcePath() == null) {
        prevType = context.contextTypes.peek().type;
      } else {
        UriInfoImpl uriInfo = (UriInfoImpl) context.contextSelectItem.getResourcePath();
        UriResource last = uriInfo.getLastResourcePart();
        if (!(last instanceof UriResourceTypedImpl)) {
          throw wrap(new UriParserSemanticException("prev segment typed",
              UriParserSemanticException.MessageKeys.PREVIOUS_PART_TYPED));
        }
        prevType = getTypeInformation(last).type;
      }

      FullQualifiedName finalTypeName = new FullQualifiedName(prevType.getNamespace(), prevType.getName());

      // check for action
      EdmAction action = edm.getBoundAction(fullName, finalTypeName, null);

      if (action != null) {
        UriResourceActionImpl uriAction = new UriResourceActionImpl();
        uriAction.setAction(action);

        UriInfoImpl resourcePath = (UriInfoImpl) context.contextSelectItem.getResourcePath();
        resourcePath.addResourcePart(uriAction);
      }

      // check for function
      EdmFunction function = edm.getBoundFunction(fullName, finalTypeName, null, null);

      if (function != null) {
        UriResourceFunctionImpl uriFunction = new UriResourceFunctionImpl();
        uriFunction.setFunction(function);

        UriInfoImpl resourcePath = (UriInfoImpl) context.contextSelectItem.getResourcePath();
        resourcePath.addResourcePart(uriFunction);
      }
    }
    return null;
  }

  @Override
  public Object visitSkip(final SkipContext ctx) {
    SkipOptionImpl skiptoken = new SkipOptionImpl();

    String text = ctx.children.get(2).getText();

    return skiptoken.setValue(Integer.parseInt(text)).setText(text);
  }

  @Override
  public Object visitSkiptoken(final 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 MethodImpl()
        .setMethod(MethodKind.STARTSWITH)
        .addParameter((ExpressionImpl) ctx.vE1.accept(this))
        .addParameter((ExpressionImpl) ctx.vE2.accept(this));
  }

  @Override
  public ExpressionImpl visitSubstringMethodCallExpr(final SubstringMethodCallExprContext ctx) {
    MethodImpl ret = new MethodImpl();
    ret.setMethod(MethodKind.SUBSTRING);
    ret.addParameter((ExpressionImpl) ctx.vE1.accept(this));
    ret.addParameter((ExpressionImpl) ctx.vE2.accept(this));

    if (ctx.vE3 != null) {
      ret.addParameter((ExpressionImpl) ctx.vE3.accept(this));
    }

    return ret;

  }

  @Override
  public ExpressionImpl visitTimeMethodCallExpr(final TimeMethodCallExprContext ctx) {
    return new MethodImpl()
        .setMethod(MethodKind.TIME)
        .addParameter((ExpressionImpl) ctx.vE1.accept(this));
  }

  @Override
  public Object visitTop(final TopContext ctx) {
    TopOptionImpl top = new TopOptionImpl();

    String text = ctx.children.get(2).getText();

    return top.setValue(Integer.parseInt(text)).setText(text);
  }

  @Override
  public ExpressionImpl visitToLowerMethodCallExpr(final ToLowerMethodCallExprContext ctx) {
    return new MethodImpl()
        .setMethod(MethodKind.TOLOWER)
        .addParameter((ExpressionImpl) ctx.vE1.accept(this));
  }

  @Override
  public ExpressionImpl visitTotalOffsetMinutesMethodCallExpr(final TotalOffsetMinutesMethodCallExprContext ctx) {
    return new MethodImpl()
        .setMethod(MethodKind.TOTALOFFSETMINUTES)
        .addParameter((ExpressionImpl) ctx.vE1.accept(this));
  }

  @Override
  public ExpressionImpl visitTotalsecondsMethodCallExpr(final TotalsecondsMethodCallExprContext ctx) {
    return new MethodImpl()
        .setMethod(MethodKind.TOTALSECONDS)
        .addParameter((ExpressionImpl) ctx.vE1.accept(this));
  }

  @Override
  public ExpressionImpl visitToUpperMethodCallExpr(final ToUpperMethodCallExprContext ctx) {
    return new MethodImpl()
        .setMethod(MethodKind.TOUPPER)
        .addParameter((ExpressionImpl) ctx.vE1.accept(this));
  }

  @Override
  public ExpressionImpl visitTrimMethodCallExpr(final TrimMethodCallExprContext ctx) {
    return new MethodImpl()
        .setMethod(MethodKind.TRIM)
        .addParameter((ExpressionImpl) ctx.vE1.accept(this));
  }

  @Override
  public ExpressionImpl visitYearMethodCallExpr(final YearMethodCallExprContext ctx) {
    return new MethodImpl()
        .setMethod(MethodKind.YEAR)
        .addParameter((ExpressionImpl) ctx.vE1.accept(this));
  }

  private ParseCancellationException wrap(final UriParserException uriParserException) {
    return new ParseCancellationException(uriParserException);
  }

  @Override
  public ExpressionImpl visitAltUnary(@NotNull UriParserParser.AltUnaryContext ctx) {
  	UnaryImpl unary = new UnaryImpl();
  	unary.setOperator(ctx.unary().NOT() == null? UnaryOperatorKind.MINUS: UnaryOperatorKind.NOT);
  	unary.setOperand((ExpressionImpl) ctx.commonExpr().accept(this));
  	return unary;
  }
  
	@Override 
	public ExpressionImpl visitAltAlias(@NotNull UriParserParser.AltAliasContext ctx) { 
		AliasImpl alias = new AliasImpl();
		alias.setParameter("@"+ctx.odataIdentifier().getChild(0).getText());
		return alias;
	}
}
