/// <summary> /// Bind a filter option /// </summary> /// <param name="syntax">a syntactic tree containing the filter option</param> /// <param name="rangeVariable">the range variable that iterates over the top level collection.</param> /// <returns>A filter clause representing this filter option</returns> public FilterClause BindFilter(SyntacticTree syntax, RangeVariable rangeVariable) { if (syntax.Filter != null) { if (rangeVariable == null) { throw new ODataException(ODataErrorStrings.MetadataBinder_QueryOptionNotApplicable("$filter")); } FilterBinder filterBinder = new FilterBinder(this.bindMethod, this.bindingState); return(filterBinder.BindFilter(syntax.Filter)); } return(null); }
/// <summary> /// Parses a <paramref name="filter"/> clause on the given <paramref name="elementType"/>, binding /// the text into semantic nodes using the provided model. /// </summary> /// <param name="filter">String representation of the filter expression.</param> /// <param name="configuration">The configuration used for binding.</param> /// <param name="elementType">Type that the filter clause refers to.</param> /// <param name="navigationSource">Navigation source that the elements being filtered are from.</param> /// <returns>A <see cref="FilterClause"/> representing the metadata bound filter expression.</returns> private FilterClause ParseFilterImplementation(string filter, ODataUriParserConfiguration configuration, IEdmType elementType, IEdmNavigationSource navigationSource) { ExceptionUtils.CheckArgumentNotNull(configuration, "configuration"); ExceptionUtils.CheckArgumentNotNull(elementType, "elementType"); ExceptionUtils.CheckArgumentNotNull(filter, "filter"); // Get the syntactic representation of the filter expression UriQueryExpressionParser expressionParser = new UriQueryExpressionParser(configuration.Settings.FilterLimit, configuration.EnableCaseInsensitiveUriFunctionIdentifier); QueryToken filterToken = expressionParser.ParseFilter(filter); // Bind it to metadata BindingState state = new BindingState(configuration); state.ImplicitRangeVariable = NodeFactory.CreateImplicitRangeVariable(elementType.ToTypeReference(), navigationSource); state.RangeVariables.Push(state.ImplicitRangeVariable); if (applyClause != null) { state.AggregatedPropertyNames = applyClause.GetLastAggregatedPropertyNames(); } MetadataBinder binder = new MetadataBinder(state); FilterBinder filterBinder = new FilterBinder(binder.Bind, state); FilterClause boundNode = filterBinder.BindFilter(filterToken); return boundNode; }
/// <summary> /// Generate an expand item (and a select item for the implicit nav prop if necessary) based on an ExpandTermToken /// </summary> /// <param name="tokenIn">the expandTerm token to visit</param> /// <returns>the expand item for this expand term token.</returns> private SelectItem GenerateExpandItem(ExpandTermToken tokenIn) { ExceptionUtils.CheckArgumentNotNull(tokenIn, "tokenIn"); // ensure that we're always dealing with proper V4 syntax if (tokenIn.PathToNavProp.NextToken != null && !tokenIn.PathToNavProp.IsNamespaceOrContainerQualified()) { if (tokenIn.PathToNavProp.NextToken.Identifier != UriQueryConstants.RefSegment || tokenIn.PathToNavProp.NextToken.NextToken != null) { throw new ODataException(ODataErrorStrings.ExpandItemBinder_TraversingMultipleNavPropsInTheSamePath); } } PathSegmentToken currentToken = tokenIn.PathToNavProp; IEdmStructuredType currentLevelEntityType = this.EdmType; List <ODataPathSegment> pathSoFar = new List <ODataPathSegment>(); PathSegmentToken firstNonTypeToken = currentToken; if (currentToken.IsNamespaceOrContainerQualified()) { pathSoFar.AddRange(SelectExpandPathBinder.FollowTypeSegments(currentToken, this.Model, this.Settings.SelectExpandLimit, this.configuration.Resolver, ref currentLevelEntityType, out firstNonTypeToken)); } IEdmProperty edmProperty = this.configuration.Resolver.ResolveProperty(currentLevelEntityType, firstNonTypeToken.Identifier); if (edmProperty == null) { throw new ODataException(ODataErrorStrings.MetadataBinder_PropertyNotDeclared(currentLevelEntityType.FullTypeName(), currentToken.Identifier)); } IEdmNavigationProperty currentNavProp = edmProperty as IEdmNavigationProperty; if (currentNavProp == null) { throw new ODataException(ODataErrorStrings.ExpandItemBinder_PropertyIsNotANavigationProperty(currentToken.Identifier, currentLevelEntityType.FullTypeName())); } bool isRef = false; if (firstNonTypeToken.NextToken != null) { // lastly... make sure that, since we're on a NavProp, that the next token isn't null. if (firstNonTypeToken.NextToken.Identifier == UriQueryConstants.RefSegment) { isRef = true; } else { throw new ODataException(ODataErrorStrings.ExpandItemBinder_TraversingMultipleNavPropsInTheSamePath); } } pathSoFar.Add(new NavigationPropertySegment(currentNavProp, /*entitySet*/ null)); ODataExpandPath pathToNavProp = new ODataExpandPath(pathSoFar); IEdmNavigationSource targetNavigationSource = null; if (this.NavigationSource != null) { targetNavigationSource = this.NavigationSource.FindNavigationTarget(currentNavProp); } // call MetadataBinder to build the filter clause FilterClause filterOption = null; if (tokenIn.FilterOption != null) { MetadataBinder binder = this.BuildNewMetadataBinder(targetNavigationSource); FilterBinder filterBinder = new FilterBinder(binder.Bind, binder.BindingState); filterOption = filterBinder.BindFilter(tokenIn.FilterOption); } // call MetadataBinder again to build the orderby clause OrderByClause orderbyOption = null; if (tokenIn.OrderByOptions != null) { MetadataBinder binder = this.BuildNewMetadataBinder(targetNavigationSource); OrderByBinder orderByBinder = new OrderByBinder(binder.Bind); orderbyOption = orderByBinder.BindOrderBy(binder.BindingState, tokenIn.OrderByOptions); } SearchClause searchOption = null; if (tokenIn.SearchOption != null) { MetadataBinder binder = this.BuildNewMetadataBinder(targetNavigationSource); SearchBinder searchBinder = new SearchBinder(binder.Bind); searchOption = searchBinder.BindSearch(tokenIn.SearchOption); } if (isRef) { return(new ExpandedReferenceSelectItem(pathToNavProp, targetNavigationSource, filterOption, orderbyOption, tokenIn.TopOption, tokenIn.SkipOption, tokenIn.CountQueryOption, searchOption)); } SelectExpandClause subSelectExpand; if (tokenIn.ExpandOption != null) { subSelectExpand = this.GenerateSubExpand(currentNavProp, tokenIn); } else { subSelectExpand = BuildDefaultSubExpand(); } subSelectExpand = this.DecorateExpandWithSelect(subSelectExpand, currentNavProp, tokenIn.SelectOption); LevelsClause levelsOption = this.ParseLevels(tokenIn.LevelsOption, currentLevelEntityType, currentNavProp); return(new ExpandedNavigationSelectItem(pathToNavProp, targetNavigationSource, subSelectExpand, filterOption, orderbyOption, tokenIn.TopOption, tokenIn.SkipOption, tokenIn.CountQueryOption, searchOption, levelsOption)); }
public ApplyBinder(MetadataBinder.QueryTokenVisitor bindMethod, BindingState state) { this.bindMethod = bindMethod; this.state = state; this.filterBinder = new FilterBinder(bindMethod, state); }
/// <summary> /// Generate an expand item (and a select item for the implicit nav prop if necessary) based on an ExpandTermToken /// </summary> /// <param name="tokenIn">the expandTerm token to visit</param> /// <returns>the expand item for this expand term token.</returns> private SelectItem GenerateExpandItem(ExpandTermToken tokenIn) { ExceptionUtils.CheckArgumentNotNull(tokenIn, "tokenIn"); // ensure that we're always dealing with proper V4 syntax if (tokenIn.PathToNavProp.NextToken != null && !tokenIn.PathToNavProp.IsNamespaceOrContainerQualified()) { if (tokenIn.PathToNavProp.NextToken.Identifier != UriQueryConstants.RefSegment || tokenIn.PathToNavProp.NextToken.NextToken != null) { throw new ODataException(ODataErrorStrings.ExpandItemBinder_TraversingMultipleNavPropsInTheSamePath); } } PathSegmentToken currentToken = tokenIn.PathToNavProp; IEdmStructuredType currentLevelEntityType = this.EdmType; List<ODataPathSegment> pathSoFar = new List<ODataPathSegment>(); PathSegmentToken firstNonTypeToken = currentToken; if (currentToken.IsNamespaceOrContainerQualified()) { pathSoFar.AddRange(SelectExpandPathBinder.FollowTypeSegments(currentToken, this.Model, this.Settings.SelectExpandLimit, this.configuration.Resolver, ref currentLevelEntityType, out firstNonTypeToken)); } IEdmProperty edmProperty = this.configuration.Resolver.ResolveProperty(currentLevelEntityType, firstNonTypeToken.Identifier); if (edmProperty == null) { throw new ODataException(ODataErrorStrings.MetadataBinder_PropertyNotDeclared(currentLevelEntityType.ODataFullName(), currentToken.Identifier)); } IEdmNavigationProperty currentNavProp = edmProperty as IEdmNavigationProperty; if (currentNavProp == null) { throw new ODataException(ODataErrorStrings.ExpandItemBinder_PropertyIsNotANavigationProperty(currentToken.Identifier, currentLevelEntityType.ODataFullName())); } bool isRef = false; if (firstNonTypeToken.NextToken != null) { // lastly... make sure that, since we're on a NavProp, that the next token isn't null. if (firstNonTypeToken.NextToken.Identifier == UriQueryConstants.RefSegment) { isRef = true; } else { throw new ODataException(ODataErrorStrings.ExpandItemBinder_TraversingMultipleNavPropsInTheSamePath); } } pathSoFar.Add(new NavigationPropertySegment(currentNavProp, /*entitySet*/null)); ODataExpandPath pathToNavProp = new ODataExpandPath(pathSoFar); IEdmNavigationSource targetNavigationSource = null; if (this.NavigationSource != null) { targetNavigationSource = this.NavigationSource.FindNavigationTarget(currentNavProp); } // call MetadataBinder to build the filter clause FilterClause filterOption = null; if (tokenIn.FilterOption != null) { MetadataBinder binder = this.BuildNewMetadataBinder(targetNavigationSource); FilterBinder filterBinder = new FilterBinder(binder.Bind, binder.BindingState); filterOption = filterBinder.BindFilter(tokenIn.FilterOption); } // call MetadataBinder again to build the orderby clause OrderByClause orderbyOption = null; if (tokenIn.OrderByOptions != null) { MetadataBinder binder = this.BuildNewMetadataBinder(targetNavigationSource); OrderByBinder orderByBinder = new OrderByBinder(binder.Bind); orderbyOption = orderByBinder.BindOrderBy(binder.BindingState, tokenIn.OrderByOptions); } SearchClause searchOption = null; if (tokenIn.SearchOption != null) { MetadataBinder binder = this.BuildNewMetadataBinder(targetNavigationSource); SearchBinder searchBinder = new SearchBinder(binder.Bind); searchOption = searchBinder.BindSearch(tokenIn.SearchOption); } if (isRef) { return new ExpandedReferenceSelectItem(pathToNavProp, targetNavigationSource, filterOption, orderbyOption, tokenIn.TopOption, tokenIn.SkipOption, tokenIn.CountQueryOption, searchOption); } SelectExpandClause subSelectExpand; if (tokenIn.ExpandOption != null) { subSelectExpand = this.GenerateSubExpand(currentNavProp, tokenIn); } else { subSelectExpand = BuildDefaultSubExpand(); } subSelectExpand = this.DecorateExpandWithSelect(subSelectExpand, currentNavProp, tokenIn.SelectOption); LevelsClause levelsOption = this.ParseLevels(tokenIn.LevelsOption, currentLevelEntityType, currentNavProp); return new ExpandedNavigationSelectItem(pathToNavProp, targetNavigationSource, subSelectExpand, filterOption, orderbyOption, tokenIn.TopOption, tokenIn.SkipOption, tokenIn.CountQueryOption, searchOption, levelsOption); }