Пример #1
0
        /// <summary>
        /// is this selection item a structural or navigation property selection item.
        /// </summary>
        /// <param name="selectItem">the selection item to check</param>
        /// <returns>true if this selection item is a structural property selection item.</returns>
        internal static bool IsStructuralOrNavigationPropertySelectionItem(SelectItem selectItem)
        {
            DebugUtils.CheckNoExternalCallers();
            PathSelectItem pathSelectItem = selectItem as PathSelectItem;

            return(pathSelectItem != null && (pathSelectItem.SelectedPath.LastSegment is NavigationPropertySegment || pathSelectItem.SelectedPath.LastSegment is PropertySegment));
        }
Пример #2
0
        private static SelectExpandClause CreateSelectExpandClauseNestedSelectWithComplexType()
        {
            ODataSelectPath personNamePath = new ODataSelectPath(new PropertySegment(HardCodedTestModel.GetPersonNameProp()));
            ODataSelectPath personShoePath = new ODataSelectPath(new PropertySegment(HardCodedTestModel.GetPersonFavoriteDateProp()));
            ODataSelectPath addrPath       = new ODataSelectPath(new PropertySegment(HardCodedTestModel.GetPersonAddressProp()));
            ODataSelectPath cityPath       = new ODataSelectPath(new PropertySegment(HardCodedTestModel.GetAddressCityProperty()));

            var cityClause = new SelectExpandClause(new List <SelectItem>(), false);

            cityClause.AddToSelectedItems(new PathSelectItem(cityPath));
            var addritem = new PathSelectItem(addrPath);

            addritem.SelectAndExpand = cityClause;

            var addritem1 = new PathSelectItem(addrPath);

            var clause = new SelectExpandClause(new List <SelectItem>(), false);

            clause.AddToSelectedItems(new PathSelectItem(personShoePath));
            clause.AddToSelectedItems(new PathSelectItem(personNamePath));
            clause.AddToSelectedItems(addritem);
            clause.AddToSelectedItems(addritem1);

            return(clause);
        }
Пример #3
0
        public void DuplicatedSelectPathInOneDollarSelectWorksAsSingle(string select, string expect)
        {
            // Arrange
            ODataQueryOptionParser parser = new ODataQueryOptionParser(_model.Model, _model.Customer, _model.Customers,
                                                                       new Dictionary <string, string> {
                { "$select", select }
            });

            // Act
            SelectExpandClause selectAndExpand = parser.ParseSelectAndExpand();

            // Assert
            Assert.NotNull(selectAndExpand);
            Assert.False(selectAndExpand.AllSelected);
            SelectItem       selectItem     = Assert.Single(selectAndExpand.SelectedItems);
            PathSelectItem   pathSelectItem = Assert.IsType <PathSelectItem>(selectItem);
            ODataPathSegment pathSegment    = Assert.Single(pathSelectItem.SelectedPath);

            if (expect == "ID")
            {
                PropertySegment propertySegment = Assert.IsType <PropertySegment>(pathSegment);
                Assert.Equal(expect, propertySegment.Identifier);
            }
            else
            {
                OperationSegment operationSegment = Assert.IsType <OperationSegment>(pathSegment);
                Assert.Equal(expect, operationSegment.Operations.Single().FullName());
            }
        }
Пример #4
0
        public void NestedTopAndSkipAndCountWithValidExpression()
        {
            // Arrange
            SelectToken select = ParseSelectToken("FavoriteColors($skip=4;$count=false;$top=2)");

            // Act
            SelectExpandClause clause = BinderForPerson.Bind(expandToken: null, selectToken: select);

            // Assert
            Assert.NotNull(clause);
            Assert.NotNull(clause.SelectedItems);

            // FavoriteColors
            SelectItem     selectItem    = Assert.Single(clause.SelectedItems);
            PathSelectItem subPathSelect = Assert.IsType <PathSelectItem>(selectItem);

            Assert.NotNull(subPathSelect.SkipOption);
            Assert.Equal(4, subPathSelect.SkipOption.Value);

            Assert.NotNull(subPathSelect.CountOption);
            Assert.False(subPathSelect.CountOption.Value);

            Assert.NotNull(subPathSelect.TopOption);
            Assert.Equal(2, subPathSelect.TopOption.Value);
        }
        private static void ValidateRestrictions(SelectExpandClause selectExpandClause, IEdmModel edmModel)
        {
            foreach (SelectItem selectItem in selectExpandClause.SelectedItems)
            {
                ExpandedNavigationSelectItem expandItem = selectItem as ExpandedNavigationSelectItem;
                if (expandItem != null)
                {
                    NavigationPropertySegment navigationSegment  = (NavigationPropertySegment)expandItem.PathToNavigationProperty.LastSegment;
                    IEdmNavigationProperty    navigationProperty = navigationSegment.NavigationProperty;
                    if (EdmLibHelpers.IsNotExpandable(navigationProperty, edmModel))
                    {
                        throw new ODataException(Error.Format(SRResources.NotExpandablePropertyUsedInExpand, navigationProperty.Name));
                    }
                    ValidateRestrictions(expandItem.SelectAndExpand, edmModel);
                }

                PathSelectItem pathSelectItem = selectItem as PathSelectItem;
                if (pathSelectItem != null)
                {
                    ODataPathSegment          segment = pathSelectItem.SelectedPath.LastSegment;
                    NavigationPropertySegment navigationPropertySegment = segment as NavigationPropertySegment;
                    if (navigationPropertySegment != null)
                    {
                        IEdmNavigationProperty navigationProperty = navigationPropertySegment.NavigationProperty;
                        if (EdmLibHelpers.IsNotNavigable(navigationProperty, edmModel))
                        {
                            throw new ODataException(Error.Format(SRResources.NotNavigablePropertyUsedInNavigation, navigationProperty.Name));
                        }
                    }
                }
            }
        }
Пример #6
0
        public override Expression Translate(PathSelectItem item)
        {
            _pathSelect = true;
            Expression expression;

            if (item.SelectedPath.LastSegment is NavigationPropertySegment)
            {
                var segment = (NavigationPropertySegment)item.SelectedPath.LastSegment;
                expression = Translate(segment, null);
            }
            else if (item.SelectedPath.LastSegment is PropertySegment)
            {
                var segment = (PropertySegment)item.SelectedPath.LastSegment;
                _selectItemInfo = new SelectItemInfo(null, segment.Property, null, null);

                PropertyInfo property = _parameter.Type.GetTypeInfo().GetProperty(segment.Property.Name);
                expression = Expression.MakeMemberAccess(_parameter, property);
            }
            else
            {
                throw new InvalidOperationException(item.SelectedPath.LastSegment.GetType().Name + " not supported");
            }

            return(expression);
        }
Пример #7
0
        private void AddStructuralProperty(IEdmStructuralProperty structuralProperty, PathSelectItem pathSelectItem)
        {
            bool isComplexOrCollectComplex = IsComplexOrCollectionComplex(structuralProperty);

            if (isComplexOrCollectComplex)
            {
                if (SelectedComplexProperties == null)
                {
                    SelectedComplexProperties = new Dictionary <IEdmStructuralProperty, PathSelectItem>();
                }

                SelectedComplexProperties[structuralProperty] = pathSelectItem;
            }
            else
            {
                if (SelectedStructuralProperties == null)
                {
                    SelectedStructuralProperties = new HashSet <IEdmStructuralProperty>();
                }

                // for primitive, enum and collection them, needn't care about the nested query options now.
                // So, skip the path select item.
                SelectedStructuralProperties.Add(structuralProperty);
            }
        }
Пример #8
0
        public void NestedSelectWithValidExpressionOnCollection()
        {
            // Arrange
            SelectToken select = ParseSelectToken("PreviousAddresses($select=Street)");

            // Act
            SelectExpandClause clause = BinderForPerson.Bind(expandToken: null, selectToken: select);

            // Assert
            Assert.NotNull(clause);

            // only one top level $select
            SelectItem selectItem = Assert.Single(clause.SelectedItems);

            // it should be "PathSelectItem
            PathSelectItem pathSelect = Assert.IsType <PathSelectItem>(selectItem);

            Assert.NotNull(pathSelect.SelectAndExpand);

            // Street
            selectItem = Assert.Single(pathSelect.SelectAndExpand.SelectedItems);
            PathSelectItem subPathSelect = Assert.IsType <PathSelectItem>(selectItem);

            Assert.Equal("Street", subPathSelect.SelectedPath.ToResourcePathString(ODataUrlKeyDelimiter.Parentheses));
            Assert.NotNull(subPathSelect.SelectAndExpand);
        }
Пример #9
0
        internal static string ParseSelect(this ODataQueryOptions options, DbUtility utility)
        {
            if (options.Count != null)
            {
                return("count(0)");
            }
            if (options.SelectExpand == null)
            {
                return("*");
            }
            if (options.SelectExpand.SelectExpandClause.AllSelected)
            {
                return("*");
            }
            List <string>  s      = new List <string>();
            PathSelectItem select = null;

            foreach (var item in options.SelectExpand.SelectExpandClause.SelectedItems)
            {
                select = item as PathSelectItem;
                if (select != null)
                {
                    foreach (PropertySegment path in select.SelectedPath)
                    {
                        s.Add(utility.SafeDbObject(path.Property.Name));
                    }
                }
            }
            return(string.Join(",", s));
        }
Пример #10
0
        internal static string ParseSelect(this ExpandedNavigationSelectItem expanded)
        {
            if (expanded.CountOption.HasValue)
            {
                return("count(*)");
            }
            if (expanded.SelectAndExpand == null)
            {
                return("*");
            }
            if (expanded.SelectAndExpand.AllSelected)
            {
                return("*");
            }
            List <string>  s      = new List <string>();
            PathSelectItem select = null;

            foreach (var item in expanded.SelectAndExpand.SelectedItems)
            {
                select = item as PathSelectItem;
                if (select != null)
                {
                    foreach (PropertySegment path in select.SelectedPath)
                    {
                        s.Add(string.Format("[{0}]", path.Property.Name));
                    }
                }
            }
            return(string.Join(",", s));
        }
Пример #11
0
        public void CreateNamedPropertyExpression_NonDerivedProperty_ReturnsMemberAccessExpression(HandleNullPropagationOption options)
        {
            SelectExpandBinder binder = GetBinder <Customer>(_model, options);

            Expression             customer            = Expression.Constant(new Customer());
            IEdmStructuralProperty homeAddressProperty = _customer.StructuralProperties().Single(c => c.Name == "HomeLocation");

            ODataSelectPath selectPath     = new ODataSelectPath(new PropertySegment(homeAddressProperty));
            PathSelectItem  pathSelectItem = new PathSelectItem(selectPath);

            NamedPropertyExpression namedProperty = binder.CreateNamedPropertyExpression(customer, _customer, pathSelectItem);

            Assert.NotNull(namedProperty);
            Assert.Equal("\"HomeLocation\"", namedProperty.Name.ToString());

            if (options != HandleNullPropagationOption.True)
            {
                Assert.Equal("value(NS.Customer).HomeLocation", namedProperty.Value.ToString());
            }
            else
            {
                Assert.Equal("IIF((value(NS.Customer) == null)," +
                             " null," +
                             " value(NS.Customer).HomeLocation)", namedProperty.Value.ToString());
            }
        }
Пример #12
0
        /// <summary>
        /// Add sub $select item for this include property.
        /// </summary>
        /// <param name="remainingSegments">The remaining segments star from this include property.</param>
        /// <param name="oldSelectItem">The old $select item.</param>
        public void AddSubSelectItem(IList <ODataPathSegment> remainingSegments, PathSelectItem oldSelectItem)
        {
            if (remainingSegments == null)
            {
                // Be noted: In ODL v7.6.1, it's not allowed duplicated properties in $select.
                // for example: "$select=abc($top=2),abc($skip=2)" is not allowed in ODL library.
                // So, don't worry about the previous setting overrided by other same path.
                // However, it's possibility in later ODL version (>=7.6.2) to allow duplicated properties in $select.
                // It that case, please update the codes here otherwise the latter will win.

                // Besides, $select=abc,abc($top=2) is not allowed in ODL 7.6.1.
                Contract.Assert(_propertySelectItem == null);
                _propertySelectItem = oldSelectItem;
            }
            else
            {
                if (_subSelectItems == null)
                {
                    _subSelectItems = new List <SelectItem>();
                }

                _subSelectItems.Add(new PathSelectItem(new ODataSelectPath(remainingSegments), oldSelectItem.NavigationSource,
                                                       oldSelectItem.SelectAndExpand, oldSelectItem.FilterOption,
                                                       oldSelectItem.OrderByOption, oldSelectItem.TopOption,
                                                       oldSelectItem.SkipOption, oldSelectItem.CountOption,
                                                       oldSelectItem.SearchOption, oldSelectItem.ComputeOption));
            }
        }
Пример #13
0
        public void CreateNamedPropertyExpression_WithMultiplePropertyAndType_ReturnsMemberAccessExpression(HandleNullPropagationOption options)
        {
            SelectExpandBinder binder = GetBinder <Customer>(_model, options);

            Expression customer = Expression.Parameter(typeof(Customer)); // output will be different.
            // Expression customer = Expression.Constant(new Customer());

            SelectExpandClause selectExpandClause = ParseSelectExpand("HomeLocation/NS.CnAddress/Street", null);

            PathSelectItem pathSelectItem = selectExpandClause.SelectedItems.First() as PathSelectItem;

            NamedPropertyExpression namedProperty = binder.CreateNamedPropertyExpression(customer, _customer, pathSelectItem);

            Assert.NotNull(namedProperty);

            /*
             * Assert.NotNull(namedProperty);
             * Assert.Equal("\"VipAddress\"", namedProperty.Name.ToString());
             *
             * if (options != HandleNullPropagationOption.True)
             * {
             *  Assert.Equal("(value(NS.Customer) As VipCustomer).VipAddress", namedProperty.Value.ToString());
             * }
             * else
             * {
             *  Assert.Equal("IIF(((value(NS.Customer) As VipCustomer) == null)," +
             *      " null," +
             *      " (value(NS.Customer) As VipCustomer).VipAddress)", namedProperty.Value.ToString());
             * }*/
        }
Пример #14
0
        public void CreateNamedPropertyExpression_WithDerivedProperty_ReturnsMemberAccessExpression(HandleNullPropagationOption options)
        {
            SelectExpandBinder binder = GetBinder <Customer>(_model, options);

            //Expression customer = Expression.Parameter(typeof(Customer)); output will be different.
            Expression             customer           = Expression.Constant(new Customer());
            IEdmStructuralProperty vipAddressProperty = _vipCustomer.StructuralProperties().Single(c => c.Name == "VipAddress");

            ODataSelectPath selectPath = new ODataSelectPath(new TypeSegment(_vipCustomer, _customer, null),
                                                             new PropertySegment(vipAddressProperty));
            PathSelectItem pathSelectItem = new PathSelectItem(selectPath);

            NamedPropertyExpression namedProperty = binder.CreateNamedPropertyExpression(customer, _customer, pathSelectItem);

            Assert.NotNull(namedProperty);
            Assert.Equal("\"VipAddress\"", namedProperty.Name.ToString());

            if (options != HandleNullPropagationOption.True)
            {
                Assert.Equal("(value(NS.Customer) As VipCustomer).VipAddress", namedProperty.Value.ToString());
            }
            else
            {
                Assert.Equal("IIF(((value(NS.Customer) As VipCustomer) == null)," +
                             " null," +
                             " (value(NS.Customer) As VipCustomer).VipAddress)", namedProperty.Value.ToString());
            }
        }
Пример #15
0
        public void CreateNamedPropertyExpression_WithMultipleProperty_ReturnsMemberAccessExpression(HandleNullPropagationOption options)
        {
            SelectExpandBinder binder = GetBinder <Customer>(_model, options);

            //Expression customer = Expression.Parameter(typeof(Customer)); output will be different.
            Expression             customer             = Expression.Constant(new Customer());
            IEdmStructuralProperty homeLocationProperty = _customer.StructuralProperties().Single(c => c.Name == "HomeLocation");

            IEdmStructuralProperty streetProperty = _address.StructuralProperties().Single(c => c.Name == "Street");

            ODataSelectPath selectPath = new ODataSelectPath(new PropertySegment(homeLocationProperty),
                                                             new PropertySegment(streetProperty));

            PathSelectItem pathSelectItem = new PathSelectItem(selectPath);

            NamedPropertyExpression namedProperty = binder.CreateNamedPropertyExpression(customer, _customer, pathSelectItem);

            Assert.NotNull(namedProperty);

            /*
             * Assert.NotNull(namedProperty);
             * Assert.Equal("\"VipAddress\"", namedProperty.Name.ToString());
             *
             * if (options != HandleNullPropagationOption.True)
             * {
             *  Assert.Equal("(value(NS.Customer) As VipCustomer).VipAddress", namedProperty.Value.ToString());
             * }
             * else
             * {
             *  Assert.Equal("IIF(((value(NS.Customer) As VipCustomer) == null)," +
             *      " null," +
             *      " (value(NS.Customer) As VipCustomer).VipAddress)", namedProperty.Value.ToString());
             * }*/
        }
Пример #16
0
        /// <summary>
        /// Handle a PathSelectItem
        /// </summary>
        /// <param name="item">the item to Handle</param>
        public override void Handle(PathSelectItem item)
        {
            var propertySegment     = item.SelectedPath.LastSegment as PropertySegment;
            var openPropertySegment = item.SelectedPath.LastSegment as DynamicPathSegment;

            // we ignore the NavigationPropertySegment since we already handle it as ExpandedNavigationSelectItem
            if (propertySegment != null || openPropertySegment != null)
            {
                List <ODataProperty> properties = this.ProjectedEntryWrapper.Resource.Properties == null ? new List <ODataProperty>() : this.ProjectedEntryWrapper.Resource.Properties.ToList();
                List <ODataNestedResourceInfoWrapper> nestedResourceInfos = this.ProjectedEntryWrapper.NestedResourceInfoWrappers == null ? new List <ODataNestedResourceInfoWrapper>() : this.ProjectedEntryWrapper.NestedResourceInfoWrappers.ToList();

                string propertyName = (propertySegment != null) ? propertySegment.Property.Name : openPropertySegment.Identifier;
                var    property     = this.OriginalEntryWrapper.Resource.Properties.SingleOrDefault(p => p.Name == propertyName);
                if (property != null)
                {
                    properties.Add(property);
                }
                else
                {
                    var nestedInfo = this.OriginalEntryWrapper.NestedResourceInfoWrappers.SingleOrDefault(n => n.NestedResourceInfo.Name == propertyName);
                    if (nestedInfo != null)
                    {
                        nestedResourceInfos.Add(nestedInfo);
                    }
                }

                this.ProjectedEntryWrapper.Resource.Properties        = properties.AsEnumerable();
                this.ProjectedEntryWrapper.NestedResourceInfoWrappers = nestedResourceInfos.ToList();
            }
        }
Пример #17
0
        public static PathSelectItem ShouldBePathSelectionItem(this SelectItem actual, ODataPath path)
        {
            PathSelectItem pathSeleteItem = actual.ShouldBeSelectedItemOfType <PathSelectItem>();

            Assert.True(pathSeleteItem.SelectedPath.Equals(path));
            return(pathSeleteItem);
        }
Пример #18
0
        private static IEnumerable <SelectItem> GetAutoExpandedNavigationSelectItems(
            IEdmEntityType baseEntityType,
            IEdmModel model,
            string alreadyExpandedNavigationSourceName,
            IEdmNavigationSource navigationSource,
            bool isAllSelected,
            bool searchDerivedTypeWhenAutoExpand)
        {
            var expandItems = new List <SelectItem>();
            var autoExpandNavigationProperties = EdmLibHelpers.GetAutoExpandNavigationProperties(baseEntityType, model,
                                                                                                 searchDerivedTypeWhenAutoExpand);

            foreach (var navigationProperty in autoExpandNavigationProperties)
            {
                if (!alreadyExpandedNavigationSourceName.Equals(navigationProperty.Name))
                {
                    IEdmEntityType       entityType = navigationProperty.DeclaringEntityType();
                    IEdmNavigationSource currentEdmNavigationSource =
                        navigationSource.FindNavigationTarget(navigationProperty);

                    if (currentEdmNavigationSource != null)
                    {
                        List <ODataPathSegment> pathSegments = new List <ODataPathSegment>()
                        {
                            new NavigationPropertySegment(navigationProperty, currentEdmNavigationSource)
                        };

                        ODataExpandPath    expandPath         = new ODataExpandPath(pathSegments);
                        SelectExpandClause selectExpandClause = new SelectExpandClause(new List <SelectItem>(),
                                                                                       true);
                        ExpandedNavigationSelectItem item = new ExpandedNavigationSelectItem(expandPath,
                                                                                             currentEdmNavigationSource, selectExpandClause);
                        if (!currentEdmNavigationSource.EntityType().Equals(entityType))
                        {
                            IEnumerable <SelectItem> nestedSelectItems = GetAutoExpandedNavigationSelectItems(
                                currentEdmNavigationSource.EntityType(),
                                model,
                                alreadyExpandedNavigationSourceName,
                                item.NavigationSource,
                                true,
                                searchDerivedTypeWhenAutoExpand);
                            selectExpandClause = new SelectExpandClause(nestedSelectItems, true);
                            item = new ExpandedNavigationSelectItem(expandPath, currentEdmNavigationSource,
                                                                    selectExpandClause);
                        }

                        expandItems.Add(item);
                        if (!isAllSelected)
                        {
                            PathSelectItem pathSelectItem = new PathSelectItem(
                                new ODataSelectPath(pathSegments));
                            expandItems.Add(pathSelectItem);
                        }
                    }
                }
            }
            return(expandItems);
        }
Пример #19
0
        private static Expression BuildOrderBySkipToken(OeSelectItem navigationItem, OrderByClause orderByClause, Expression source, OeJoinBuilder joinBuilder, bool hasSelectItems)
        {
            while (orderByClause != null)
            {
                var propertyNode = (SingleValuePropertyAccessNode)orderByClause.Expression;
                if (propertyNode.Source is SingleNavigationNode navigationNode)
                {
                    OeSelectItem match = null;
                    ExpandedNavigationSelectItem navigationSelectItem = null;
                    do
                    {
                        if ((match = navigationItem.FindHierarchyNavigationItem(navigationNode.NavigationProperty)) != null)
                        {
                            match.AddSelectItem(new OeSelectItem(propertyNode.Property, true));
                            break;
                        }

                        SelectExpandClause selectExpandClause;
                        if (navigationSelectItem == null)
                        {
                            var pathSelectItem = new PathSelectItem(new ODataSelectPath(new PropertySegment((IEdmStructuralProperty)propertyNode.Property)));
                            selectExpandClause = new SelectExpandClause(new[] { pathSelectItem }, false);
                        }
                        else
                        {
                            selectExpandClause = new SelectExpandClause(new[] { navigationSelectItem }, false);
                        }

                        var segment = new NavigationPropertySegment(navigationNode.NavigationProperty, navigationNode.NavigationSource);
                        navigationSelectItem = new ExpandedNavigationSelectItem(new ODataExpandPath(segment), navigationNode.NavigationSource, selectExpandClause);
                    }while ((navigationNode = navigationNode.Source as SingleNavigationNode) != null);

                    if (navigationSelectItem != null)
                    {
                        if (match == null)
                        {
                            match = navigationItem;
                        }

                        var selectItemTranslator = new OeSelectItemTranslator(match, false, source, joinBuilder, true);
                        navigationSelectItem.TranslateWith(selectItemTranslator);
                        source = selectItemTranslator.Source;
                    }
                }
                else
                {
                    if (hasSelectItems)
                    {
                        navigationItem.AddSelectItem(new OeSelectItem(propertyNode.Property, true));
                    }
                }

                orderByClause = orderByClause.ThenBy;
            }

            return(source);
        }
Пример #20
0
        public void TopOptionSetCorrectly()
        {
            // Arrange & Act
            PathSelectItem select = new PathSelectItem(new ODataSelectPath(), null, null, null, null, 5, null, null, null, null);

            // Assert
            Assert.NotNull(select.TopOption);
            Assert.Equal(5, select.TopOption.Value);
        }
Пример #21
0
        public void CountQueryOptionSetCorrectly()
        {
            // Arrange & Act
            PathSelectItem select = new PathSelectItem(new ODataSelectPath(), null, null, null, null, null, null, true, null, null);

            // Assert
            Assert.NotNull(select.CountOption);
            Assert.True(select.CountOption.Value);
        }
Пример #22
0
        public void ComputeOptionSetCorrectly()
        {
            // Arrange & Act
            ComputeClause  compute = new ComputeClause(null);
            PathSelectItem select  = new PathSelectItem(new ODataSelectPath(), null, null, null, null, null, null, null, null, compute);

            // Assert
            Assert.NotNull(select.ComputeOption);
            Assert.Same(compute, select.ComputeOption);
        }
Пример #23
0
        public void SelectExpandOptionSetCorrectly()
        {
            // Arrange & Act
            SelectExpandClause selectAndExpand = new SelectExpandClause(null, true);
            PathSelectItem     select          = new PathSelectItem(new ODataSelectPath(), null, selectAndExpand, null, null, null, null, null, null, null);

            // Assert
            Assert.NotNull(select.SelectAndExpand);
            Assert.Same(selectAndExpand, select.SelectAndExpand);
        }
Пример #24
0
        public void NavigationSourceOptionSetCorrectly()
        {
            // Arrange & Act
            var            navigationSource = HardCodedTestModel.GetPeopleSet();
            PathSelectItem select           = new PathSelectItem(new ODataSelectPath(), navigationSource, null, null, null, null, null, null, null, null);

            // Assert
            Assert.NotNull(select.NavigationSource);
            Assert.Same(navigationSource, select.NavigationSource);
        }
Пример #25
0
        public void SearchOptionSetCorrectly()
        {
            // Arrange & Act
            SearchClause   search = new SearchClause(new SearchTermNode("SearchMe"));
            PathSelectItem select = new PathSelectItem(new ODataSelectPath(), null, null, null, null, null, null, null, search, null);

            // Assert
            Assert.NotNull(select.SearchOption);
            select.SearchOption.Expression.ShouldBeSearchTermNode("SearchMe");
        }
        public void PathSelectionItemIsNotImplemented()
        {
            FakeHandler    handler = new FakeHandler();
            PathSelectItem item    = new PathSelectItem(new ODataSelectPath()
            {
                new PropertySegment(ModelBuildingHelpers.BuildValidPrimitiveProperty())
            });
            Action visitPath = () => item.HandleWith(handler);

            visitPath.ShouldThrow <NotImplementedException>();
        }
Пример #27
0
        private void ProcessTokenAsPath(NonSystemToken tokenIn)
        {
            Debug.Assert(tokenIn != null, "tokenIn != null");

            List <ODataPathSegment> pathSoFar        = new List <ODataPathSegment>();
            IEdmStructuredType      currentLevelType = this.edmType;

            // first, walk through all type segments in a row, converting them from tokens into segments.
            if (tokenIn.IsNamespaceOrContainerQualified())
            {
                PathSegmentToken firstNonTypeToken;
                pathSoFar.AddRange(SelectExpandPathBinder.FollowTypeSegments(tokenIn, this.model, this.maxDepth, ref currentLevelType, out firstNonTypeToken));
                Debug.Assert(firstNonTypeToken != null, "Did not get last token.");
                tokenIn = firstNonTypeToken as NonSystemToken;
                if (tokenIn == null)
                {
                    throw new ODataException(ODataErrorStrings.SelectPropertyVisitor_SystemTokenInSelect(firstNonTypeToken.Identifier));
                }
            }

            // next, create a segment for the first non-type segment in the path.
            ODataPathSegment lastSegment = SelectPathSegmentTokenBinder.ConvertNonTypeTokenToSegment(tokenIn, this.model, currentLevelType);

            // next, create an ODataPath and add the segments to it.
            if (lastSegment != null)
            {
                pathSoFar.Add(lastSegment);
            }

            ODataSelectPath selectedPath = new ODataSelectPath(pathSoFar);

            var selectionItem = new PathSelectItem(selectedPath);

            // non-navigation cases do not allow further segments in $select.
            if (tokenIn.NextToken != null)
            {
                throw new ODataException(ODataErrorStrings.SelectBinder_MultiLevelPathInSelect);
            }

            // if the selected item is a nav prop, then see if its already there before we add it.
            NavigationPropertySegment trailingNavPropSegment = selectionItem.SelectedPath.LastSegment as NavigationPropertySegment;

            if (trailingNavPropSegment != null)
            {
                if (this.expandClauseToDecorate.SelectedItems.Any(x => x is PathSelectItem &&
                                                                  ((PathSelectItem)x).SelectedPath.Equals(selectedPath)))
                {
                    return;
                }
            }

            this.expandClauseToDecorate.AddToSelectedItems(selectionItem);
        }
Пример #28
0
        public void FilterOptionSetCorrectly()
        {
            // Arrange & Act
            BinaryOperatorNode filterExpression = new BinaryOperatorNode(BinaryOperatorKind.Equal, new ConstantNode(1), new ConstantNode(1));
            FilterClause       filterClause     = new FilterClause(filterExpression,
                                                                   new ResourceRangeVariable(ExpressionConstants.It, HardCodedTestModel.GetPersonTypeReference(), HardCodedTestModel.GetPeopleSet()));
            PathSelectItem select = new PathSelectItem(new ODataSelectPath(), null, null, filterClause, null, null, null, null, null, null);

            // Assert
            Assert.NotNull(select.FilterOption);
            Assert.Same(filterClause, select.FilterOption);
        }
Пример #29
0
        public void OrderbySetCorrectly()
        {
            // Arrange & Act
            SingleValuePropertyAccessNode propertyAccessNode = new SingleValuePropertyAccessNode(new ConstantNode(1), HardCodedTestModel.GetPersonNameProp());
            OrderByClause orderBy = new OrderByClause(null, propertyAccessNode, OrderByDirection.Descending,
                                                      new ResourceRangeVariable(ExpressionConstants.It, HardCodedTestModel.GetPersonTypeReference(), HardCodedTestModel.GetPeopleSet()));
            PathSelectItem select = new PathSelectItem(new ODataSelectPath(), null, null, null, orderBy, null, null, null, null, null);

            // Assert
            Assert.NotNull(select.OrderByOption);
            Assert.Same(orderBy, select.OrderByOption);
        }
Пример #30
0
        private static void HandlePathSelectItem(SelectStatement statement, PathSelectItem item)
        {
            var property = item.SelectedPath.FirstSegment as PropertySegment;

            if (property != null)
            {
                statement.Columns(property.Property.Name);
            }
            else
            {
                throw new NotSupportedException(string.Format("PathSelectItem type '{0}' is not supported.", item.SelectedPath.FirstSegment.GetType().FullName));
            }
        }
        /// <summary>
        /// Handle a PathSelectItem
        /// </summary>
        /// <param name="item">the item to Handle</param>
        public override void Handle(PathSelectItem item)
        {
            var propertySegment = item.SelectedPath.LastSegment as PropertySegment;
            var openPropertySegment = item.SelectedPath.LastSegment as OpenPropertySegment;

            // we ignore the NavigationPropertySegment since we already handle it as ExpandedNavigationSelectItem
            if (propertySegment != null || openPropertySegment != null)
            {
                List<ODataProperty> properties = this.ProjectedEntry.Properties == null ? new List<ODataProperty>() : this.ProjectedEntry.Properties.ToList();

                string propertyName = (propertySegment != null) ? propertySegment.Property.Name : openPropertySegment.PropertyName;
                properties.Add(this.OriginalEntry.Properties.Single(p => p.Name == propertyName));

                this.ProjectedEntry.Properties = properties.AsEnumerable();
            }
        }
Пример #32
0
        private static IEnumerable<SelectItem> GetAutoExpandedNavigationSelectItems(
            IEdmEntityType baseEntityType, 
            IEdmModel model,
            string alreadyExpandedNavigationSourceName,
            IEdmNavigationSource navigationSource,
            bool isAllSelected,
            bool searchDerivedTypeWhenAutoExpand)
        {
            var expandItems = new List<SelectItem>();
            var autoExpandNavigationProperties = EdmLibHelpers.GetAutoExpandNavigationProperties(baseEntityType, model,
                searchDerivedTypeWhenAutoExpand);
            foreach (var navigationProperty in autoExpandNavigationProperties)
            {
                if (!alreadyExpandedNavigationSourceName.Equals(navigationProperty.Name))
                {
                    IEdmEntityType entityType = navigationProperty.DeclaringEntityType();
                    IEdmNavigationSource currentEdmNavigationSource =
                        navigationSource.FindNavigationTarget(navigationProperty);

                    if (currentEdmNavigationSource != null)
                    {
                        List<ODataPathSegment> pathSegments = new List<ODataPathSegment>()
                        {
                            new NavigationPropertySegment(navigationProperty, currentEdmNavigationSource)
                        };

                        ODataExpandPath expandPath = new ODataExpandPath(pathSegments);
                        SelectExpandClause selectExpandClause = new SelectExpandClause(new List<SelectItem>(),
                            true);
                        ExpandedNavigationSelectItem item = new ExpandedNavigationSelectItem(expandPath,
                            currentEdmNavigationSource, selectExpandClause);
                        if (!currentEdmNavigationSource.EntityType().Equals(entityType))
                        {
                            IEnumerable<SelectItem> nestedSelectItems = GetAutoExpandedNavigationSelectItems(
                                currentEdmNavigationSource.EntityType(),
                                model,
                                alreadyExpandedNavigationSourceName,
                                item.NavigationSource,
                                true,
                                searchDerivedTypeWhenAutoExpand);
                            selectExpandClause = new SelectExpandClause(nestedSelectItems, true);
                            item = new ExpandedNavigationSelectItem(expandPath, currentEdmNavigationSource,
                                selectExpandClause);
                        }

                        expandItems.Add(item);
                        if (!isAllSelected)
                        {
                            PathSelectItem pathSelectItem = new PathSelectItem(
                                new ODataSelectPath(pathSegments));
                            expandItems.Add(pathSelectItem);
                        }
                    }
                }
            }
            return expandItems;
        }
        // Process $levels in ExpandedNavigationSelectItem.
        private ExpandedNavigationSelectItem ProcessLevels(
            ExpandedNavigationSelectItem expandItem,
            int levelsMaxLiteralExpansionDepth,
            out bool levelsEncounteredInExpand,
            out bool isMaxLevelInExpand)
        {
            int level;
            isMaxLevelInExpand = false;

            // $level=x
            if (expandItem.LevelsOption != null && !expandItem.LevelsOption.IsMaxLevel)
            {
                levelsEncounteredInExpand = true;
                level = (int)expandItem.LevelsOption.Level;
                if (LevelsMaxLiteralExpansionDepth < 0)
                {
                    levelsMaxLiteralExpansionDepth = level;
                }
            }
            else
            {
                if (levelsMaxLiteralExpansionDepth < 0)
                {
                    levelsMaxLiteralExpansionDepth = ODataValidationSettings.DefaultMaxExpansionDepth;
                }

                if (expandItem.LevelsOption == null)
                {
                    // no $level
                    levelsEncounteredInExpand = false;
                    level = 1;
                }
                else
                {
                    // $level=max
                    levelsEncounteredInExpand = true;
                    isMaxLevelInExpand = true;
                    level = levelsMaxLiteralExpansionDepth;
                }
            }

            // Do not expand when:
            // 1. $levels is equal to or less than 0.
            // 2. $levels value is greater than current MaxExpansionDepth
            if (level <= 0 || level > levelsMaxLiteralExpansionDepth)
            {
                return null;
            }

            ExpandedNavigationSelectItem item = null;
            SelectExpandClause currentSelectExpandClause = null;
            SelectExpandClause selectExpandClause = null;
            bool levelsEncounteredInInnerExpand = false;
            bool isMaxLevelInInnerExpand = false;

            // Try diffent expansion depth until expandItem.SelectAndExpand is successfully expanded
            while (selectExpandClause == null && level > 0)
            {
                selectExpandClause = ProcessLevels(
                        expandItem.SelectAndExpand,
                        levelsMaxLiteralExpansionDepth - level,
                        out levelsEncounteredInInnerExpand,
                        out isMaxLevelInInnerExpand);
                level--;
            }

            if (selectExpandClause == null)
            {
                return null;
            }

            // Correct level value
            level++;

            var entityType = expandItem.NavigationSource.EntityType();
            string alreadyExpandedNavigationSourceName =
                (expandItem.PathToNavigationProperty.LastSegment as NavigationPropertySegment).NavigationProperty.Name;
            IEnumerable<SelectItem> autoExpandNavigationSelectItems = GetAutoExpandedNavigationSelectItems(
                entityType,
                Context.Model,
                alreadyExpandedNavigationSourceName, 
                expandItem.NavigationSource, 
                selectExpandClause.AllSelected);
            bool hasAutoExpandInExpand = (autoExpandNavigationSelectItems.Count() != 0);

            while (level > 0)
            {
                if (item == null)
                {
                    if (hasAutoExpandInExpand)
                    {
                        currentSelectExpandClause = new SelectExpandClause(
                            new SelectItem[] { }.Concat(selectExpandClause.SelectedItems)
                                .Concat(autoExpandNavigationSelectItems),
                            selectExpandClause.AllSelected);
                    }
                    else
                    {
                        currentSelectExpandClause = selectExpandClause;
                    }
                }
                else if (selectExpandClause.AllSelected)
                {
                    // Concat the processed items
                    currentSelectExpandClause = new SelectExpandClause(
                        new SelectItem[] { item }.Concat(selectExpandClause.SelectedItems)
                            .Concat(autoExpandNavigationSelectItems),
                        selectExpandClause.AllSelected);
                }
                else
                {
                    // PathSelectItem is needed for the expanded item if AllSelected is false. 
                    PathSelectItem pathSelectItem = new PathSelectItem(
                        new ODataSelectPath(expandItem.PathToNavigationProperty));

                    // Keep default SelectItems before expanded item to keep consistent with normal SelectExpandClause 
                    SelectItem[] items = new SelectItem[] { item, pathSelectItem };
                    currentSelectExpandClause = new SelectExpandClause(
                        new SelectItem[] { }.Concat(selectExpandClause.SelectedItems)
                            .Concat(items)
                            .Concat(autoExpandNavigationSelectItems),
                        selectExpandClause.AllSelected);
                }

                // Construct a new ExpandedNavigationSelectItem with current SelectExpandClause.
                item = new ExpandedNavigationSelectItem(
                    expandItem.PathToNavigationProperty,
                    expandItem.NavigationSource,
                    currentSelectExpandClause);

                level--;

                // Need expand and construct selectExpandClause every time if it is max level in inner expand
                if (isMaxLevelInInnerExpand) 
                {
                    selectExpandClause = ProcessLevels(
                        expandItem.SelectAndExpand,
                        levelsMaxLiteralExpansionDepth - level,
                        out levelsEncounteredInInnerExpand,
                        out isMaxLevelInInnerExpand);
                }
            }

            levelsEncounteredInExpand = levelsEncounteredInExpand || levelsEncounteredInInnerExpand || hasAutoExpandInExpand;
            isMaxLevelInExpand = isMaxLevelInExpand || isMaxLevelInInnerExpand;

            return item;
        }
Пример #34
0
 public void ConstructorShouldSetPropertyName()
 {
     var item = new PathSelectItem(new ODataSelectPath(new OpenPropertySegment("abc")));
     item.SelectedPath.FirstSegment.ShouldBeOpenPropertySegment("abc");
 }
Пример #35
0
 /// <summary>
 /// Handle a PathSelectItem
 /// </summary>
 /// <param name="item">the item to Handle</param>
 public virtual void Handle(PathSelectItem item)
 {
     throw new NotImplementedException();
 }
Пример #36
0
        private void ProcessTokenAsPath(NonSystemToken tokenIn)
        {
            Debug.Assert(tokenIn != null, "tokenIn != null");

            List<ODataPathSegment> pathSoFar = new List<ODataPathSegment>();
            IEdmStructuredType currentLevelType = this.edmType;

            // first, walk through all type segments in a row, converting them from tokens into segments.
            if (tokenIn.IsNamespaceOrContainerQualified())
            {
                PathSegmentToken firstNonTypeToken;
                pathSoFar.AddRange(SelectExpandPathBinder.FollowTypeSegments(tokenIn, this.model, this.maxDepth, this.resolver, ref currentLevelType, out firstNonTypeToken));
                Debug.Assert(firstNonTypeToken != null, "Did not get last token.");
                tokenIn = firstNonTypeToken as NonSystemToken;
                if (tokenIn == null)
                {
                    throw new ODataException(ODataErrorStrings.SelectPropertyVisitor_SystemTokenInSelect(firstNonTypeToken.Identifier));
                }  
            }

            // next, create a segment for the first non-type segment in the path.
            ODataPathSegment lastSegment = SelectPathSegmentTokenBinder.ConvertNonTypeTokenToSegment(tokenIn, this.model, currentLevelType, resolver);

            // next, create an ODataPath and add the segments to it.
            if (lastSegment != null)
            {
                pathSoFar.Add(lastSegment);

                bool hasCollectionInPath = false;

                // try create a complex type property path.
                while (true)
                {
                    // no need to go on if the current property is not of complex type or collection of complex type.
                    currentLevelType = lastSegment.EdmType as IEdmStructuredType;
                    var collectionType = lastSegment.EdmType as IEdmCollectionType;
                    if ((currentLevelType == null || currentLevelType.TypeKind != EdmTypeKind.Complex) 
                        && (collectionType == null || collectionType.ElementType.TypeKind() != EdmTypeKind.Complex))
                    {
                        break;
                    }

                    NonSystemToken nextToken = tokenIn.NextToken as NonSystemToken;
                    if (nextToken == null)
                    {
                        break;
                    }

                    lastSegment = null;

                    // This means last segment a collection of complex type,
                    // current segment can only be type cast and cannot be proprty name.
                    if (currentLevelType == null)
                    {
                        currentLevelType = collectionType.ElementType.Definition as IEdmStructuredType;
                        hasCollectionInPath = true;
                    }
                    else if (!hasCollectionInPath)
                    {
                        // If there is no collection type in the path yet, will try to bind property for the next token
                        // first try bind the segment as property.
                        lastSegment = SelectPathSegmentTokenBinder.ConvertNonTypeTokenToSegment(nextToken, this.model,
                            currentLevelType, resolver);
                    }

                    // then try bind the segment as type cast.
                    if (lastSegment == null)
                    {
                        IEdmStructuredType typeFromNextToken = UriEdmHelpers.FindTypeFromModel(this.model, nextToken.Identifier, this.resolver) as IEdmStructuredType;

                        if (typeFromNextToken.IsOrInheritsFrom(currentLevelType))
                        {
                            lastSegment = new TypeSegment(typeFromNextToken, /*entitySet*/null);
                        }
                    }

                    // type cast failed too.
                    if (lastSegment == null)
                    {
                        break;
                    }

                    // try move to and add next path segment.
                    tokenIn = nextToken;
                    pathSoFar.Add(lastSegment);
                }
            }

            ODataSelectPath selectedPath = new ODataSelectPath(pathSoFar);

            var selectionItem = new PathSelectItem(selectedPath);

            // non-navigation cases do not allow further segments in $select.
            if (tokenIn.NextToken != null)
            {
                throw new ODataException(ODataErrorStrings.SelectBinder_MultiLevelPathInSelect);
            }

            // if the selected item is a nav prop, then see if its already there before we add it.
            NavigationPropertySegment trailingNavPropSegment = selectionItem.SelectedPath.LastSegment as NavigationPropertySegment;
            if (trailingNavPropSegment != null)
            {
                if (this.expandClauseToDecorate.SelectedItems.Any(x => x is PathSelectItem &&
                    ((PathSelectItem)x).SelectedPath.Equals(selectedPath)))
                {
                    return;
                }
            }

            this.expandClauseToDecorate.AddToSelectedItems(selectionItem);         
        }
        // Process $levels in ExpandedNavigationSelectItem.
        private static ExpandedNavigationSelectItem ProcessLevels(
            ExpandedNavigationSelectItem expandItem,
            int levelsMaxLiteralExpansionDepth,
            out bool levelsEncounteredInExpand)
        {
            // Call ProcessLevels on SelectExpandClause recursively.
            SelectExpandClause selectExpandClause = ProcessLevels(
                expandItem.SelectAndExpand,
                levelsMaxLiteralExpansionDepth - 1,
                out levelsEncounteredInExpand);

            if (expandItem.LevelsOption == null)
            {
                if (levelsEncounteredInExpand)
                {
                    return new ExpandedNavigationSelectItem(
                        expandItem.PathToNavigationProperty,
                        expandItem.NavigationSource,
                        selectExpandClause);
                }
                else
                {
                    // Return the original ExpandedNavigationSelectItem if no $levels is found.
                    return expandItem;
                }
            }

            // There is $levels in current ExpandedNavigationSelectItem.
            levelsEncounteredInExpand = true;
            int level = expandItem.LevelsOption.IsMaxLevel ?
                levelsMaxLiteralExpansionDepth :
                (int)expandItem.LevelsOption.Level;

            if (level <= 0)
            {
                // Do not expand if $levels is equal to 0.
                return null;
            }

            // Initialize current SelectExpandClause with processed SelectExpandClause.
            SelectExpandClause currentSelectExpandClause = selectExpandClause;
            ExpandedNavigationSelectItem item = null;

            // Construct new ExpandedNavigationSelectItem with recursive expansion.
            while (level > 0)
            {
                // Construct a new ExpandedNavigationSelectItem with current SelectExpandClause.
                item = new ExpandedNavigationSelectItem(
                    expandItem.PathToNavigationProperty,
                    expandItem.NavigationSource,
                    currentSelectExpandClause);

                // Update current SelectExpandClause with the new ExpandedNavigationSelectItem.
                if (selectExpandClause.AllSelected)
                {
                    currentSelectExpandClause = new SelectExpandClause(
                        new[] { item }.Concat(selectExpandClause.SelectedItems),
                        selectExpandClause.AllSelected);
                }
                else
                {
                    // PathSelectItem is needed for the expanded item if AllSelected is false. 
                    PathSelectItem pathSelectItem = new PathSelectItem(
                        new ODataSelectPath(expandItem.PathToNavigationProperty));
                    currentSelectExpandClause = new SelectExpandClause(
                        new SelectItem[] { item, pathSelectItem }.Concat(selectExpandClause.SelectedItems),
                        selectExpandClause.AllSelected);
                }

                level--;
            }

            return item;
        }
Пример #38
0
 /// <summary>
 /// Writes Selection Item of type PathSelectItem node to string
 /// </summary>
 /// <param name="node">Node to write to string</param>
 /// <returns>String representation of node.</returns>
 private static string ToString(PathSelectItem node)
 {
     return ToSingleLineString(node.SelectedPath);
 }
        // Process $levels in ExpandedNavigationSelectItem.
        private static ExpandedNavigationSelectItem ProcessLevels(
            ExpandedNavigationSelectItem expandItem,
            int levelsMaxLiteralExpansionDepth,
            out bool levelsEncounteredInExpand,
            out bool isMaxLevelInExpand)
        {
            int level;
            isMaxLevelInExpand = false;

            if (expandItem.LevelsOption == null)
            {
                levelsEncounteredInExpand = false;
                level = 1;
            }
            else
            {
                levelsEncounteredInExpand = true;
                if (expandItem.LevelsOption.IsMaxLevel)
                {
                    isMaxLevelInExpand = true;
                    level = levelsMaxLiteralExpansionDepth;
                }
                else
                {
                    level = (int)expandItem.LevelsOption.Level;
                }
            }

            // Do not expand when:
            // 1. $levels is equal to or less than 0.
            // 2. $levels value is greater than current MaxExpansionDepth
            if (level <= 0 || level > levelsMaxLiteralExpansionDepth)
            {
                return null;
            }

            ExpandedNavigationSelectItem item = null;
            SelectExpandClause currentSelectExpandClause = null;
            SelectExpandClause selectExpandClause = null;
            bool levelsEncounteredInInnerExpand = false;
            bool isMaxLevelInInnerExpand = false;

            // Try diffent expansion depth until expandItem.SelectAndExpand is successfully expanded
            while (selectExpandClause == null && level > 0)
            {
                selectExpandClause = ProcessLevels(
                        expandItem.SelectAndExpand,
                        levelsMaxLiteralExpansionDepth - level,
                        out levelsEncounteredInInnerExpand,
                        out isMaxLevelInInnerExpand);
                level--;
            }

            if (selectExpandClause == null)
            {
                return null;
            }

            // Correct level value
            level++;

            while (level > 0)
            {
                if (item == null)
                {
                    currentSelectExpandClause = selectExpandClause;
                }
                else if (selectExpandClause.AllSelected)
                {
                    // Concat the processed items
                    currentSelectExpandClause = new SelectExpandClause(
                        new SelectItem[] { item }.Concat(selectExpandClause.SelectedItems),
                        selectExpandClause.AllSelected);
                }
                else
                {
                    // PathSelectItem is needed for the expanded item if AllSelected is false. 
                    PathSelectItem pathSelectItem = new PathSelectItem(
                        new ODataSelectPath(expandItem.PathToNavigationProperty));

                    // Keep default SelectItems before expanded item to keep consistent with normal SelectExpandClause 
                    SelectItem[] items = new SelectItem[] { item, pathSelectItem };
                    currentSelectExpandClause = new SelectExpandClause(
                        new SelectItem[] { }.Concat(selectExpandClause.SelectedItems).Concat(items),
                        selectExpandClause.AllSelected);
                }

                // Construct a new ExpandedNavigationSelectItem with current SelectExpandClause.
                item = new ExpandedNavigationSelectItem(
                    expandItem.PathToNavigationProperty,
                    expandItem.NavigationSource,
                    currentSelectExpandClause);

                level--;

                // Need expand and construct selectExpandClause every time if it is max level in inner expand
                if (isMaxLevelInInnerExpand) 
                {
                    selectExpandClause = ProcessLevels(
                        expandItem.SelectAndExpand,
                        levelsMaxLiteralExpansionDepth - level,
                        out levelsEncounteredInInnerExpand,
                        out isMaxLevelInInnerExpand);
                }
            }

            levelsEncounteredInExpand = levelsEncounteredInExpand || levelsEncounteredInInnerExpand;
            isMaxLevelInExpand = isMaxLevelInExpand || isMaxLevelInInnerExpand;

            return item;
        }