/// <summary> /// Visit a NonSystemToken /// </summary> /// <param name="tokenIn">the non sytem token to visit</param> public override void Visit(NonSystemToken tokenIn) { ExceptionUtils.CheckArgumentNotNull(tokenIn, "tokenIn"); // before looking for type segments or paths, handle both of the wildcard cases. if (tokenIn.NextToken == null) { SelectItem newSelectItem; if (SelectPathSegmentTokenBinder.TryBindAsWildcard(tokenIn, this.model, out newSelectItem)) { this.expandClauseToDecorate.AddSelectItem(newSelectItem); return; } } this.ProcessTokenAsPath(tokenIn); }
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); } }
/// <summary> /// Visit an NonSystemToken /// </summary> /// <param name="tokenIn">The System token to visit</param> /// <returns>A user defined class</returns> public virtual T Visit(NonSystemToken tokenIn) { throw new NotImplementedException(); }