Ejemplo n.º 1
0
        /// <summary>
        /// Binds a <see cref="SyntacticTree"/>.
        /// </summary>
        /// <param name="syntax">The query descriptor token to bind.</param>
        /// <returns>The bound query descriptor.</returns>
        public ODataUri BindTree(SyntacticTree syntax)
        {
            ExceptionUtils.CheckArgumentNotNull(syntax, "syntax");
            ExceptionUtils.CheckArgumentNotNull(syntax.Path, "syntax.Path");

            // Make a copy of query options since we may consume some of them as we bind the query
            bindingState.QueryOptions = new List <CustomQueryOptionToken>(syntax.QueryOptions);

            ODataPath          path         = null;
            FilterClause       filter       = null;
            OrderByClause      orderBy      = null;
            long?              skip         = null;
            long?              top          = null;
            SelectExpandClause selectExpand = null;
            InlineCountKind?   inlineCount  = null;

            // First bind the path
            path = ODataPathFactory.BindPath(syntax.Path, this.bindingState.Configuration);

            // If the path leads to a collection, then create a range variable that represents iterating over the collection
            var rangeVariable = NodeFactory.CreateImplicitRangeVariable(path);

            if (rangeVariable != null)
            {
                this.bindingState.RangeVariables.Push(rangeVariable);
            }

            if (syntax.Filter != null || syntax.OrderByTokens.Any())
            {
                this.bindingState.ImplicitRangeVariable = this.bindingState.RangeVariables.Peek();
            }

            // Apply filter first, then order-by, skip, top, select and expand
            filter = BindFilter(syntax, rangeVariable);

            orderBy = BindOrderBy(syntax, rangeVariable, path);

            skip = BindSkip(syntax, rangeVariable, path);

            top = BindTop(syntax, rangeVariable, path);

            selectExpand = BindSelectExpand(syntax, path, this.bindingState.Configuration);

            inlineCount = BindInlineCount(syntax, path);

            // Add the remaining query options to the query descriptor.
            List <QueryNode> boundQueryOptions = MetadataBinder.ProcessQueryOptions(this.bindingState, this.bindMethod);

            Debug.Assert(bindingState.QueryOptions == null, "this.queryOptions == null");
            bindingState.RangeVariables.Pop();
            bindingState.ImplicitRangeVariable = null;

            return(new ODataUri(path, boundQueryOptions, selectExpand, filter, orderBy, skip, top, inlineCount));
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Bind a select and expand option.
        /// </summary>
        /// <param name="syntax">A syntax tree containing the select and expand options to bind</param>
        /// <param name="path">the top level path</param>
        /// <param name="configuration">The configuration to use for binding.</param>
        /// <returns>a select expand clause bound to metadata</returns>
        public static SelectExpandClause BindSelectExpand(SyntacticTree syntax, ODataPath path, ODataUriParserConfiguration configuration)
        {
            if (syntax.Select != null || syntax.Expand != null)
            {
                if (!path.EdmType().IsEntityCollection() && !path.EdmType().IsEntity())
                {
                    throw new ODataException(ODataErrorStrings.MetadataBinder_QueryOptionNotApplicable("$select or $expand"));
                }

                return(SelectExpandSemanticBinder.Parse((IEdmEntityType)((IEdmCollectionTypeReference)path.EdmType()).ElementType().Definition, path.EntitySet(), syntax.Expand, syntax.Select, configuration));
            }

            return(null);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Bind a skip option
        /// </summary>
        /// <param name="syntax">a syntax tree containing the skip option</param>
        /// <param name="rangeVariable">the range variable that iterates over the top level collection</param>
        /// <param name="path">the top level path.</param>
        /// <returns>a nullable long representing this skip option</returns>
        public static long?BindSkip(SyntacticTree syntax, RangeVariable rangeVariable, ODataPath path)
        {
            if (syntax.Skip != null)
            {
                if (rangeVariable == null || !path.EdmType().IsEntityCollection())
                {
                    throw new ODataException(ODataErrorStrings.MetadataBinder_QueryOptionNotApplicable("$skip"));
                }

                return(MetadataBinder.ProcessSkip(syntax.Skip));
            }

            return(null);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Bind an inline count option
        /// </summary>
        /// <param name="syntax">The inline count option to bind.</param>
        /// <param name="path">the top level path</param>
        /// <returns>an InlineCountKind representing this inline count option</returns>
        public static InlineCountKind?BindInlineCount(SyntacticTree syntax, ODataPath path)
        {
            if (syntax.InlineCount != null)
            {
                if (!path.EdmType().IsEntityCollection())
                {
                    throw new ODataException(ODataErrorStrings.MetadataBinder_QueryOptionNotApplicable("$inlinecount"));
                }

                return(syntax.InlineCount.Value);
            }

            return(null);
        }
Ejemplo n.º 5
0
        /// <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);
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Bind an orderby option
        /// </summary>
        /// <param name="syntax">a syntac tree containing the orderby option</param>
        /// <param name="rangeVariable">the range variable that iterates over the top level collection</param>
        /// <param name="path">the top level path</param>
        /// <returns>an OrderByClause representing this orderby option</returns>
        public OrderByClause BindOrderBy(SyntacticTree syntax, RangeVariable rangeVariable, ODataPath path)
        {
            if (syntax.OrderByTokens != null && syntax.OrderByTokens.Any())
            {
                if (rangeVariable == null || !path.EdmType().IsEntityCollection())
                {
                    throw new ODataException(ODataErrorStrings.MetadataBinder_QueryOptionNotApplicable("$orderby"));
                }

                OrderByBinder orderByBinder = new OrderByBinder(this.bindMethod);
                return(orderByBinder.BindOrderBy(this.bindingState, syntax.OrderByTokens));
            }

            return(null);
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Parses the full Uri.
        /// </summary>
        /// <param name="fullUri">The full uri to parse</param>
        /// <returns>An ODataUri representing the full uri</returns>
        private ODataUri ParseUriImplementation(Uri fullUri)
        {
            ExceptionUtils.CheckArgumentNotNull(this.configuration.Model, "model");
            ExceptionUtils.CheckArgumentNotNull(this.configuration.ServiceRoot, "serviceRoot");
            ExceptionUtils.CheckArgumentNotNull(fullUri, "fullUri");

            SyntacticTree syntax = SyntacticTree.ParseUri(fullUri, this.configuration.ServiceRoot, this.Settings.FilterLimit);

            ExceptionUtils.CheckArgumentNotNull(syntax, "syntax");
            BindingState           state     = new BindingState(this.configuration);
            MetadataBinder         binder    = new MetadataBinder(state);
            ODataUriSemanticBinder uriBinder = new ODataUriSemanticBinder(state, binder.Bind);

            return(uriBinder.BindTree(syntax));
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Create a URI for the given queryDescriptor given the base service URI.
        /// </summary>
        /// <param name="baseUri">The base service URI.</param>
        /// <param name="queryDescriptor">The query descriptor to create the result URI from.</param>
        /// <returns>An absolute URI that base on the baseUri and represent the queryDescriptor.</returns>
        public static Uri CreateUri(Uri baseUri, SyntacticTree queryDescriptor)
        {
            ExceptionUtils.CheckArgumentNotNull(baseUri, "baseUri");
            ExceptionUtils.CheckArgumentNotNull(queryDescriptor, "queryDescriptor");

            ODataUriBuilder odataUriBuilder = new ODataUriBuilder(queryDescriptor);
            string          uriPart         = odataUriBuilder.Build();

            if (uriPart.StartsWith(ExpressionConstants.SymbolQueryStart, StringComparison.Ordinal))
            {
                UriBuilder uriBuilder = new UriBuilder(baseUri);
                uriBuilder.Query = uriPart;
                return(uriBuilder.Uri);
            }

            return(new Uri(baseUri, new Uri(uriPart, UriKind.RelativeOrAbsolute)));
        }
Ejemplo n.º 9
0
 /// <summary>
 /// Create a new Uri builder for the given token.
 /// </summary>
 /// <param name="query">The token to write out as Uri.</param>
 private ODataUriBuilder(SyntacticTree query)
 {
     this.query = query;
 }
Ejemplo n.º 10
0
        /// <summary>
        /// Write the descriptor token as URI part to this builder.
        /// </summary>
        /// <param name="queryDescriptor">To write as URI part.</param>
        public void WriteQueryDescriptor(SyntacticTree queryDescriptor)
        {
            ExceptionUtils.CheckArgumentNotNull(queryDescriptor, "queryDescriptor");

            this.WritePath(queryDescriptor.Path);

            bool writeQueryPrefix = true;

            if (queryDescriptor.Filter != null)
            {
                this.WriteQueryPrefixOrSeparator(writeQueryPrefix);
                writeQueryPrefix = false;

                this.builder.Append(UriQueryConstants.FilterQueryOption);
                this.builder.Append(ExpressionConstants.SymbolEqual);
                this.WriteQuery(queryDescriptor.Filter);
            }

            if (queryDescriptor.Select != null && queryDescriptor.Select.Properties.Count() > 0)
            {
                this.WriteQueryPrefixOrSeparator(writeQueryPrefix);
                writeQueryPrefix = false;

                this.WriteSelect(queryDescriptor.Select);
            }

            if (queryDescriptor.Expand != null && queryDescriptor.Expand.ExpandTerms.Count() > 0)
            {
                this.WriteQueryPrefixOrSeparator(writeQueryPrefix);
                writeQueryPrefix = false;

                this.WriteExpand(queryDescriptor.Expand);
            }

            if (queryDescriptor.OrderByTokens.Count() > 0)
            {
                this.WriteQueryPrefixOrSeparator(writeQueryPrefix);
                writeQueryPrefix = false;

                this.builder.Append(UriQueryConstants.OrderByQueryOption);
                this.builder.Append(ExpressionConstants.SymbolEqual);

                this.WriteOrderBys(queryDescriptor.OrderByTokens);
            }

            foreach (CustomQueryOptionToken queryOption in queryDescriptor.QueryOptions)
            {
                this.WriteQueryPrefixOrSeparator(writeQueryPrefix);
                writeQueryPrefix = false;

                this.WriteQueryOption(queryOption);
            }

            if (queryDescriptor.Top != null)
            {
                this.WriteQueryPrefixOrSeparator(writeQueryPrefix);
                writeQueryPrefix = false;

                this.builder.Append(UriQueryConstants.TopQueryOption);
                this.builder.Append(ExpressionConstants.SymbolEqual);
                this.builder.Append(queryDescriptor.Top);
            }

            if (queryDescriptor.Skip != null)
            {
                this.WriteQueryPrefixOrSeparator(writeQueryPrefix);
                writeQueryPrefix = false;

                this.builder.Append(UriQueryConstants.SkipQueryOption);
                this.builder.Append(ExpressionConstants.SymbolEqual);
                this.builder.Append(queryDescriptor.Skip);
            }

            if (queryDescriptor.Format != null)
            {
                this.WriteQueryPrefixOrSeparator(writeQueryPrefix);
                writeQueryPrefix = false;

                this.builder.Append(UriQueryConstants.FormatQueryOption);
                this.builder.Append(ExpressionConstants.SymbolEqual);
                this.builder.Append(queryDescriptor.Format);
            }

            if (queryDescriptor.InlineCount.HasValue)
            {
                this.WriteQueryPrefixOrSeparator(writeQueryPrefix);
                writeQueryPrefix = false;

                this.builder.Append(UriQueryConstants.InlineCountQueryOption);
                this.builder.Append(ExpressionConstants.SymbolEqual);
                this.builder.Append(queryDescriptor.InlineCount.Value.ToText());
            }
        }