Пример #1
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);
        }
        public void GetFirstNonTypeCastSegment_WorksForSelectPathWithFirstNonTypeSegmentAtMiddle()
        {
            // Arrange
            EdmEntityType          entityType = new EdmEntityType("NS", "Customer");
            IEdmStructuralProperty property   = entityType.AddStructuralProperty("Id", EdmPrimitiveTypeKind.String);

            ODataPathSegment firstTypeSegment      = new TypeSegment(entityType, null);
            ODataPathSegment secondTypeSegment     = new TypeSegment(entityType, null);
            ODataPathSegment firstPropertySegment  = new PropertySegment(property);
            ODataPathSegment secondPropertySegment = new PropertySegment(property);
            ODataSelectPath  selectPath            = new ODataSelectPath(
                firstTypeSegment,
                secondTypeSegment,
                firstPropertySegment, // here
                secondPropertySegment);

            // Act
            IList <ODataPathSegment> remainingSegments;
            ODataPathSegment         firstNonTypeSegment = selectPath.GetFirstNonTypeCastSegment(out remainingSegments);

            // Assert
            Assert.NotNull(firstNonTypeSegment);
            Assert.Same(firstPropertySegment, firstNonTypeSegment);

            Assert.NotNull(remainingSegments);
            Assert.Same(secondPropertySegment, Assert.Single(remainingSegments));
        }
Пример #3
0
        public static int GetCacheCode(int hash, SelectExpandClause selectExpandClause)
        {
            foreach (SelectItem selectItem in selectExpandClause.SelectedItems)
            {
                if (selectItem is ExpandedNavigationSelectItem)
                {
                    var expanded = selectItem as ExpandedNavigationSelectItem;
                    hash = CombineHashCodes(hash, expanded.NavigationSource.Name.GetHashCode());
                    if (expanded.SelectAndExpand != null)
                    {
                        hash = CombineHashCodes(hash, GetCacheCode(hash, expanded.SelectAndExpand));
                    }
                }
                else if (selectItem is PathSelectItem)
                {
                    ODataSelectPath path = (selectItem as PathSelectItem).SelectedPath;
                    hash = CombineHashCodes(hash, path.FirstSegment.Identifier.GetHashCode());
                    hash = CombineHashCodes(hash, path.LastSegment.Identifier.GetHashCode());
                }
                else
                {
                    throw new InvalidOperationException("unknown SelectItem " + selectItem.GetType().ToString());
                }
            }

            return(hash);
        }
        public void GetFirstNonTypeCastSegment_SelectPath_ThrowsArgumentNull()
        {
            // Arrange & Act
            ODataSelectPath          selectPath = null;
            IList <ODataPathSegment> remainingSegments;

            // Assert
            ExceptionAssert.ThrowsArgumentNull(() => selectPath.GetFirstNonTypeCastSegment(out remainingSegments), "selectPath");
        }
Пример #5
0
        public void SuccessfullyAddSelectionItems()
        {
            ODataSelectPath personNamePath = new ODataSelectPath(new PropertySegment(HardCodedTestModel.GetPersonNameProp()));
            ODataSelectPath personShoePath = new ODataSelectPath(new PropertySegment(HardCodedTestModel.GetPersonShoeProp()));
            var             clause         = new SelectExpandClause(new List <ExpandedNavigationSelectItem>(), false);

            clause.AddToSelectedItems(new PathSelectItem(personShoePath));
            clause.AddToSelectedItems(new PathSelectItem(personNamePath));
            clause.SelectedItems.Should().HaveCount(2).And.Contain(x => x is PathSelectItem && x.As <PathSelectItem>().SelectedPath == personNamePath).And.Contain(x => x is PathSelectItem && x.As <PathSelectItem>().SelectedPath == personShoePath);
        }
        public void GetFirstNonTypeCastSegment_ThrowsForUnsupportedMiddleSegmentInSelectPath()
        {
            // Arrange & Act
            ODataSelectPath          selectPath = new ODataSelectPath(new DynamicPathSegment("abc"), new DynamicPathSegment("xyz"));
            IList <ODataPathSegment> remainingSegments;

            // Assert
            ExceptionAssert.Throws <ODataException>(() => selectPath.GetFirstNonTypeCastSegment(out remainingSegments),
                                                    String.Format(SRResources.InvalidSegmentInSelectExpandPath, "DynamicPathSegment"));
        }
        public void GetFirstNonTypeCastSegment_ThrowsForUnsupportedLastSegmentInSelectPath()
        {
            // Arrange & Act
            IEdmType                 stringType = EdmCoreModel.Instance.GetString(false).Definition;
            ODataSelectPath          selectPath = new ODataSelectPath(new TypeSegment(stringType, null), new TypeSegment(stringType, null));
            IList <ODataPathSegment> remainingSegments;

            // Assert
            ExceptionAssert.Throws <ODataException>(() => selectPath.GetFirstNonTypeCastSegment(out remainingSegments),
                                                    String.Format(SRResources.InvalidLastSegmentInSelectExpandPath, "TypeSegment"));
        }
        public void SuccessfullyAddSelectionItems()
        {
            ODataSelectPath personNamePath = new ODataSelectPath(new PropertySegment(HardCodedTestModel.GetPersonNameProp()));
            ODataSelectPath personShoePath = new ODataSelectPath(new PropertySegment(HardCodedTestModel.GetPersonShoeProp()));
            var             clause         = new SelectExpandClause(new List <ExpandedNavigationSelectItem>(), false);

            clause.AddToSelectedItems(new PathSelectItem(personShoePath));
            clause.AddToSelectedItems(new PathSelectItem(personNamePath));
            Assert.Equal(2, clause.SelectedItems.Count());
            Assert.Contains(clause.SelectedItems, x => x is PathSelectItem && ((PathSelectItem)x).SelectedPath == personNamePath);
            Assert.Contains(clause.SelectedItems, x => x is PathSelectItem && ((PathSelectItem)x).SelectedPath == personShoePath);
        }
Пример #9
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);
        }
Пример #10
0
        private static SelectExpandClause CreateSelectExpandClauseMultiSelect()
        {
            ODataSelectPath personNamePath = new ODataSelectPath(new PropertySegment(HardCodedTestModel.GetPersonNameProp()));
            ODataSelectPath personShoePath = new ODataSelectPath(new PropertySegment(HardCodedTestModel.GetPersonShoeProp()));

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

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

            return(clause);
        }
Пример #11
0
        public void TestSelectAndExpand3()
        {
            ODataSelectPath path = new ODataSelectPath();
            var             selectExpandClause = new ODataQueryOptionParser(_model, this._customer, _customers,
                                                                            new Dictionary <string, string>
            {
                { "$expand", "" },
                { "$select", "Locations/Street,Locations/Region" }
                // { "$select", "Locations/NS.CnAddress" } // this should be same as "$select=Locations"
            }).ParseSelectAndExpand();

            Assert.NotNull(selectExpandClause);
        }
Пример #12
0
        public void PathExtensionsToExpandPathWithNonNavigationPropertyThrows()
        {
            var             property = mbh.BuildValidPrimitiveProperty();
            ODataSelectPath path     = new ODataSelectPath(
                new ODataPathSegment[]
            {
                new PropertySegment(HardCodedTestModel.GetPersonNameProp())
            }
                );

            Action expandPathAction = () => path.ToExpandPath();

            expandPathAction.Throws <ODataException>(ODataErrorStrings.ODataExpandPath_OnlyLastSegmentMustBeNavigationProperty);
        }
Пример #13
0
        public void PathExtensionsToExpandPathWithNavigationPropertyReturnsExpandedPath()
        {
            var             property = mbh.BuildValidPrimitiveProperty();
            ODataSelectPath path     = new ODataSelectPath(
                new ODataPathSegment[]
            {
                new NavigationPropertySegment(
                    HardCodedTestModel.GetPersonMyDogNavProp(), HardCodedTestModel.GetDogsSet())
            }
                );

            Assert.Equal(1, path.ToExpandPath().Count);
            Assert.Equal("MyDog", path.ToExpandPath().FirstSegment.Identifier);
        }
Пример #14
0
        /// <summary>
        /// Verify the $select path and gets the first non type cast segment in a select path.
        /// For example: $select=NS.SubType1/abc/NS.SubType2/xyz
        /// => firstPropertySegment: "abc"
        /// => remainingSegments:  NS.SubType2/xyz
        /// </summary>
        /// <param name="selectPath">The input $select path.</param>
        /// <param name="remainingSegments">The remaining segments after the first non type segment.</param>
        /// <returns>First non-type cast segment.</returns>
        public static ODataPathSegment GetFirstNonTypeCastSegment(this ODataSelectPath selectPath,
                                                                  out IList <ODataPathSegment> remainingSegments)
        {
            if (selectPath == null)
            {
                throw new ArgumentNullException(nameof(selectPath));
            }

            // In fact, ODataSelectPath constructor verifies the supporting segments, we add the verification here for double check.
            return(GetFirstNonTypeCastSegment(selectPath,
                                              //The middle segment should be "TypeSegment" or "PropertySegment".
                                              m => m is PropertySegment || m is TypeSegment,
                                              // The last segment could be "NavigationPropertySegment, PropertySegment, OperationSegment, DynamicPathSegment"
                                              s => s is NavigationPropertySegment || s is PropertySegment || s is OperationSegment || s is DynamicPathSegment,
                                              out remainingSegments));
        }
Пример #15
0
        public void WildcardDoesNotPreemptOtherSelectionItems()
        {
            // Arrange
            ODataSelectPath coolPeoplePath = new ODataSelectPath(new OperationSegment(new[] { HardCodedTestModel.GetColorAtPositionFunction() }, null));
            ODataSelectPath stuffPath      = new ODataSelectPath(new DynamicPathSegment("stuff"));

            SelectExpandBinder binderForPainting = new SelectExpandBinder(this.V4configuration,
                                                                          new ODataPathInfo(HardCodedTestModel.GetPaintingType(), null), null);

            SelectToken selectToken = new SelectToken(new SelectTermToken[]
            {
                new SelectTermToken(new NonSystemToken("Fully.Qualified.Namespace.GetColorAtPosition", null, null)), // operation
                new SelectTermToken(new NonSystemToken("Owner", null, null)),                                        // navigation property
                new SelectTermToken(new NonSystemToken("stuff", null, null)),                                        // dynamic property
                new SelectTermToken(new NonSystemToken("Colors", null, null)),                                       // structural property
                new SelectTermToken(new NonSystemToken("*", null, null))                                             // *
            });

            // Act
            SelectExpandClause clause = binderForPainting.Bind(null, selectToken);

            // Assert
            Assert.NotNull(clause);
            Assert.Equal(4, clause.SelectedItems.Count());

            // one is "*"
            Assert.Single(clause.SelectedItems.OfType <WildcardSelectItem>());

            IList <PathSelectItem> pathSelectItems = clause.SelectedItems.OfType <PathSelectItem>().ToList();

            Assert.Equal(3, pathSelectItems.Count);
            Assert.Contains(pathSelectItems, (x) => x.SelectedPath.Equals(coolPeoplePath));
            Assert.Contains(pathSelectItems, (x) => x.SelectedPath.Equals(stuffPath));
            Assert.Contains(pathSelectItems, (x) =>
            {
                NavigationPropertySegment segment = x.SelectedPath.LastSegment as NavigationPropertySegment;
                if (segment != null)
                {
                    return(segment.NavigationProperty.Name == "Owner");
                }

                return(false);
            });
        }
Пример #16
0
        public void WildcardDoesNotPreemptOtherSelectionItems()
        {
            ODataSelectPath coolPeoplePath = new ODataSelectPath(new OperationSegment(new[] { HardCodedTestModel.GetChangeStateAction() }, null));
            ODataSelectPath stuffPath      = new ODataSelectPath(new DynamicPathSegment("stuff"));
            var             expandTree     = new SelectExpandClause(new Collection <SelectItem>()
            {
                new PathSelectItem(coolPeoplePath),
                new PathSelectItem(new ODataSelectPath(new NavigationPropertySegment(HardCodedTestModel.GetPaintingOwnerNavProp(), null))),
                new PathSelectItem(stuffPath),
                new PathSelectItem(new ODataSelectPath(new PropertySegment(HardCodedTestModel.GetPaintingColorsProperty())))
            }, false);
            var binder      = new SelectBinder(HardCodedTestModel.TestModel, HardCodedTestModel.GetPaintingType(), 800, expandTree, DefaultUriResolver, null);
            var selectToken = new SelectToken(new List <PathSegmentToken>()
            {
                new NonSystemToken("*", null, null)
            });
            var item = binder.Bind(selectToken);

            item.SelectedItems.Should().HaveCount(4)
            .And.Contain(x => x is PathSelectItem && x.As <PathSelectItem>().SelectedPath == coolPeoplePath)
            .And.Contain(x => x is PathSelectItem && x.As <PathSelectItem>().SelectedPath == stuffPath)
            .And.Contain(x => x is PathSelectItem && x.As <PathSelectItem>().SelectedPath.LastSegment is NavigationPropertySegment && x.As <PathSelectItem>().SelectedPath.LastSegment.As <NavigationPropertySegment>().NavigationProperty.Name == HardCodedTestModel.GetPaintingOwnerNavProp().Name)
            .And.Contain(x => x is WildcardSelectItem);
        }
Пример #17
0
        private void ProcessTokenAsPath(NonSystemToken tokenIn)
        {
            Debug.Assert(tokenIn != null, "tokenIn != null");

            List <ODataPathSegment> pathSoFar = new List <ODataPathSegment>();
            IEdmEntityType          currentLevelEntityType = this.entityType;

            // 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 currentLevelEntityType, 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, currentLevelEntityType);

            Debug.Assert(lastSegment != null, "nextSegment != null");

            // next, create an ODataPath and add the segments to it.
            pathSoFar.Add(lastSegment);
            ODataSelectPath selectedPath = new ODataSelectPath(pathSoFar);

            var navigationSelection = new PathSelectItem(selectedPath);

            // next, create a selection item for the path, based on the last segment's type.
            // TODO: just have PathSelectItem
            if (lastSegment is NavigationPropertySegment)
            {
                bool foundExactExpand         = false;
                bool foundDifferentTypeExpand = false;
                foreach (var subItem in this.expandClauseToDecorate.Expansion.ExpandItems)
                {
                    IEdmNavigationProperty subItemNavigationProperty = subItem.PathToNavigationProperty.GetNavigationProperty();
                    if (subItem.PathToNavigationProperty.Equals(navigationSelection.SelectedPath))
                    {
                        foundExactExpand = true;

                        if (tokenIn.NextToken == null)
                        {
                            subItem.SelectAndExpand.SetAllSelectionRecursively();
                        }
                        else
                        {
                            SelectPropertyVisitor nextLevelVisitor = new SelectPropertyVisitor(this.model, subItemNavigationProperty.ToEntityType(), this.maxDepth, subItem.SelectAndExpand);
                            tokenIn.NextToken.Accept(nextLevelVisitor);
                        }
                    }
                    else if (subItem.PathToNavigationProperty.LastSegment.Equals(navigationSelection.SelectedPath.LastSegment))
                    {
                        foundDifferentTypeExpand = true;
                    }
                }

                if (foundDifferentTypeExpand && !foundExactExpand)
                {
                    throw new ODataException(ODataErrorStrings.SelectPropertyVisitor_DisparateTypeSegmentsInSelectExpand);
                }

                if (!foundExactExpand)
                {
                    // if it has sub-properties selected, then require it to have been expanded.
                    if (tokenIn.NextToken != null)
                    {
                        throw new ODataException(ODataErrorStrings.SelectionItemBinder_NoExpandForSelectedProperty(tokenIn.Identifier));
                    }

                    // otherwise just add it to the partial selection.
                    this.expandClauseToDecorate.AddSelectItem(navigationSelection);
                }
                else
                {
                    this.expandClauseToDecorate.InitializeEmptySelection();
                }
            }
            else
            {
                // non-navigation cases do not allow further segments in $select.
                if (tokenIn.NextToken != null)
                {
                    throw new ODataException(ODataErrorStrings.SelectionItemBinder_NonNavigationPathToken);
                }

                this.expandClauseToDecorate.AddSelectItem(navigationSelection);
            }
        }
Пример #18
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);

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

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

                    // 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);
        }
Пример #19
0
        private void GetAutoSelectExpandItems(IEdmEntityType baseEntityType, IEdmModel model, IEdmNavigationSource navigationSource, bool isAllSelected,
                                              ModelBoundQuerySettings modelBoundQuerySettings, int depth, out List <SelectItem> autoSelectItems, out List <SelectItem> autoExpandItems)
        {
            autoSelectItems = new List <SelectItem>();
            autoExpandItems = new List <SelectItem>();

            if (baseEntityType == null)
            {
                return;
            }

            IList <SelectModelPath> autoSelectProperties = model.GetAutoSelectPaths(baseEntityType, null, modelBoundQuerySettings);

            foreach (var autoSelectProperty in autoSelectProperties)
            {
                ODataSelectPath odataSelectPath = BuildSelectPath(autoSelectProperty, navigationSource);
                PathSelectItem  pathSelectItem  = new PathSelectItem(odataSelectPath);
                autoSelectItems.Add(pathSelectItem);
            }

            depth--;
            if (depth < 0)
            {
                return;
            }

            IList <ExpandModelPath> autoExpandNavigationProperties = model.GetAutoExpandPaths(baseEntityType, null, !isAllSelected, modelBoundQuerySettings);

            foreach (ExpandModelPath itemPath in autoExpandNavigationProperties)
            {
                string navigationPath = itemPath.NavigationPropertyPath;
                IEdmNavigationProperty navigationProperty = itemPath.Navigation;

                IEdmNavigationSource currentEdmNavigationSource;
                if (navigationPath != null)
                {
                    currentEdmNavigationSource = navigationSource.FindNavigationTarget(navigationProperty);
                }
                else
                {
                    currentEdmNavigationSource = navigationSource.FindNavigationTarget(navigationProperty, new EdmPathExpression(navigationPath));
                }

                if (currentEdmNavigationSource != null)
                {
                    ODataExpandPath expandPath = BuildExpandPath(itemPath, navigationSource, currentEdmNavigationSource);

                    SelectExpandClause           selectExpandClause = new SelectExpandClause(new List <SelectItem>(), true);
                    ExpandedNavigationSelectItem item = new ExpandedNavigationSelectItem(expandPath, currentEdmNavigationSource, selectExpandClause);
                    modelBoundQuerySettings = model.GetModelBoundQuerySettings(navigationProperty, navigationProperty.ToEntityType());
                    List <SelectItem> nestedSelectItems;
                    List <SelectItem> nestedExpandItems;

                    int maxExpandDepth = GetMaxExpandDepth(modelBoundQuerySettings, navigationProperty.Name);
                    if (maxExpandDepth != 0 && maxExpandDepth < depth)
                    {
                        depth = maxExpandDepth;
                    }

                    GetAutoSelectExpandItems(
                        currentEdmNavigationSource.EntityType(),
                        model,
                        item.NavigationSource,
                        true,
                        modelBoundQuerySettings,
                        depth,
                        out nestedSelectItems,
                        out nestedExpandItems);

                    selectExpandClause = new SelectExpandClause(nestedSelectItems.Concat(nestedExpandItems), nestedSelectItems.Count == 0);
                    item = new ExpandedNavigationSelectItem(expandPath, currentEdmNavigationSource, selectExpandClause);

                    autoExpandItems.Add(item);
                    if (!isAllSelected || autoSelectProperties.Any())
                    {
                        PathSelectItem pathSelectItem = new PathSelectItem(new ODataSelectPath(expandPath));
                        autoExpandItems.Add(pathSelectItem);
                    }
                }
            }
        }
Пример #20
0
        /// <summary>
        /// Build the $select item, it maybe $select=complex/abc, $select=abc, $select=nav, etc.
        /// </summary>
        /// <param name="pathSelectItem">The expanded reference select item.</param>
        /// <param name="currentLevelPropertiesInclude">The current properties to include at current level.</param>
        /// <param name="structuralTypeInfo">The structural type properties.</param>
        private void BuildSelectItem(PathSelectItem pathSelectItem,
                                     IDictionary <IEdmStructuralProperty, SelectExpandIncludedProperty> currentLevelPropertiesInclude,
                                     EdmStructuralTypeInfo structuralTypeInfo)
        {
            Contract.Assert(pathSelectItem != null && pathSelectItem.SelectedPath != null);
            Contract.Assert(currentLevelPropertiesInclude != null);
            Contract.Assert(structuralTypeInfo != null);

            // Verify and process the $select=abc/xyz/....
            ODataSelectPath          selectPath = pathSelectItem.SelectedPath;
            IList <ODataPathSegment> remainingSegments;
            ODataPathSegment         segment = selectPath.GetFirstNonTypeCastSegment(out remainingSegments);

            PropertySegment firstPropertySegment = segment as PropertySegment;

            if (firstPropertySegment != null)
            {
                if (structuralTypeInfo.IsStructuralPropertyDefined(firstPropertySegment.Property))
                {
                    // $select=abc/xyz/...
                    SelectExpandIncludedProperty newPropertySelectItem;
                    if (!currentLevelPropertiesInclude.TryGetValue(firstPropertySegment.Property, out newPropertySelectItem))
                    {
                        newPropertySelectItem = new SelectExpandIncludedProperty(firstPropertySegment);
                        currentLevelPropertiesInclude[firstPropertySegment.Property] = newPropertySelectItem;
                    }

                    newPropertySelectItem.AddSubSelectItem(remainingSegments, pathSelectItem);
                }

                return;
            }

            // If the first segment is not a property segment,
            // that segment must be the last segment, so the remainging segments should be null.
            Contract.Assert(remainingSegments == null);

            NavigationPropertySegment navigationSegment = segment as NavigationPropertySegment;

            if (navigationSegment != null)
            {
                // for example: $select=NavigationProperty or $select=NS.VipCustomer/VipNav
                if (structuralTypeInfo.IsNavigationPropertyDefined(navigationSegment.NavigationProperty))
                {
                    if (SelectedNavigationProperties == null)
                    {
                        SelectedNavigationProperties = new HashSet <IEdmNavigationProperty>();
                    }

                    SelectedNavigationProperties.Add(navigationSegment.NavigationProperty);
                }

                return;
            }

            OperationSegment operationSegment = segment as OperationSegment;

            if (operationSegment != null)
            {
                // for example: $select=NS.Operation, or, $select=NS.VipCustomer/NS.Operation
                AddOperations(operationSegment, structuralTypeInfo.AllActions, structuralTypeInfo.AllFunctions);
                return;
            }

            DynamicPathSegment dynamicPathSegment = segment as DynamicPathSegment;

            if (dynamicPathSegment != null)
            {
                if (SelectedDynamicProperties == null)
                {
                    SelectedDynamicProperties = new HashSet <string>();
                }

                SelectedDynamicProperties.Add(dynamicPathSegment.Identifier);
                return;
            }

            // In fact, we should never be here, because it's verified above
            throw new ODataException(Error.Format(SRResources.SelectionTypeNotSupported, segment.GetType().Name));
        }
Пример #21
0
 /// <summary>
 /// Constructs a <see cref="SelectItem"/> to indicate that a specific path is selected.
 /// </summary>
 /// <param name="selectedPath">The selected path.</param>
 /// <exception cref="System.ArgumentNullException">Throws if the input selectedPath is null.</exception>
 public PathSelectItem(ODataSelectPath selectedPath)
 {
     ExceptionUtils.CheckArgumentNotNull(selectedPath, "selectedPath");
     this.selectedPath = selectedPath;
 }