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 WildcardDoesNotPreemptOtherSelectionItems() { ODataSelectPath coolPeoplePath = new ODataSelectPath(new OperationSegment(new IEdmOperation[] { HardCodedTestModel.GetChangeStateAction() }, null)); ODataSelectPath stuffPath = new ODataSelectPath(new OpenPropertySegment("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); 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); }
/// <summary> /// Translate an ODataSelectPath into an ODataExpandPath /// Depending on the constructor of ODataExpandPath to validate that we aren't adding any /// segments that are illegal for an expand. /// </summary> /// <param name="path">the ODataSelectPath to translate</param> /// <returns>A new ODataExpand path with the same segments as the select path.</returns> public static ODataExpandPath ToExpandPath(this ODataSelectPath path) { return(new ODataExpandPath(path)); }
/// <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; }
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); }