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)); }
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"); }
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); }
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); }
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); }
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); }
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); }
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); }
/// <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)); }
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); }); }
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); }
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); } }
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); }
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); } } } }
/// <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)); }
/// <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; }