Пример #1
0
        /// <summary>
        /// Parses the <paramref name="queryUri"/> and binds the query to the metadata provided
        /// then returns a new instance of <see cref="QueryDescriptorQueryNode"/>
        /// describing the query specified by the uri.
        /// </summary>
        /// <param name="queryUri">The absolute URI which holds the query to parse. This must be a path relative to the <paramref name="serviceBaseUri"/>.</param>
        /// <param name="serviceBaseUri">The base URI of the service.</param>
        /// <param name="metadataProvider">The metadata provider to use for binding.</param>
        /// <param name="maxDepth">The maximum depth of any single query part. Security setting to guard against DoS attacks causing stack overflows and such.</param>
        /// <returns>A new instance of <see cref="QueryDescriptorQueryNode"/> which represents the query specified in the <paramref name="queryUri"/>.</returns>
        public static QueryDescriptorQueryNode ParseUri(Uri queryUri, Uri serviceBaseUri, IDataServiceMetadataProvider metadataProvider, int maxDepth)
        {
            ExceptionUtils.CheckArgumentNotNull(metadataProvider, "metadataProvider");

            QueryDescriptorQueryToken queryDescriptorQueryToken = QueryDescriptorQueryToken.ParseUri(queryUri, serviceBaseUri, maxDepth);
            MetadataBinder            metadataBinder            = new MetadataBinder(metadataProvider);

            return(metadataBinder.BindQuery(queryDescriptorQueryToken));
        }
Пример #2
0
        public void TestParseTypeSetAccess()
        {
            var parseTree = QueryDescriptorQueryToken.ParseUri(new Uri("http://example.org/odata/Films"), new Uri("http://example.org/odata/"));

            Assert.IsNotNull(parseTree);
            Assert.AreEqual(QueryTokenKind.Segment, parseTree.Path.Kind);
            var segment = parseTree.Path as SegmentQueryToken;

            Assert.AreEqual("Films", segment.Name);
            Assert.IsNull(segment.NamedValues);
        }
Пример #3
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, QueryDescriptorQueryToken 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));
        }
Пример #4
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, QueryDescriptorQueryToken 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)));
        }
Пример #5
0
        public void TestParseInstanceAccess()
        {
            var parseTree = QueryDescriptorQueryToken.ParseUri(
                new Uri("http://example.org/odata/Films('Un_Chien_Andalou')"),
                new Uri("http://example.org/odata/"));

            Assert.IsNotNull(parseTree);
            Assert.IsNotNull(parseTree.Path);
            Assert.AreEqual(QueryTokenKind.Segment, parseTree.Path.Kind);
            Assert.IsInstanceOfType(parseTree.Path, typeof(SegmentQueryToken));
            var sqt = parseTree.Path as SegmentQueryToken;

            Assert.AreEqual("Films", sqt.Name);
            Assert.IsNotNull(sqt.NamedValues);
            var namedValues = sqt.NamedValues.ToList();

            Assert.AreEqual(1, namedValues.Count);
            Assert.IsNull(namedValues[0].Name);
            Assert.IsNotNull(namedValues[0].Value);
            Assert.IsNotNull(namedValues[0].Value.Value);
            Assert.AreEqual(QueryTokenKind.Literal, namedValues[0].Value.Kind);
            Assert.AreEqual("Un_Chien_Andalou", namedValues[0].Value.Value);
        }
Пример #6
0
        /// <summary>
        /// Binds the specified <paramref name="queryDescriptorQueryToken"/> to the metadata and returns a bound query.
        /// </summary>
        /// <param name="queryDescriptorQueryToken">The lexical query descriptor for the query to process.</param>
        /// <returns>Metadata bound semantic query descriptor for the query.</returns>
        public QueryDescriptorQueryNode BindQuery(QueryDescriptorQueryToken queryDescriptorQueryToken)
        {
            ExceptionUtils.CheckArgumentNotNull(queryDescriptorQueryToken, "queryDescriptorQueryToken");

            return this.BindQueryDescriptor(queryDescriptorQueryToken);
        }
Пример #7
0
        /// <summary>
        /// Binds a <see cref="QueryDescriptorQueryToken"/>.
        /// </summary>
        /// <param name="queryDescriptorToken">The query descriptor token to bind.</param>
        /// <returns>The bound query descriptor.</returns>
        protected virtual QueryDescriptorQueryNode BindQueryDescriptor(QueryDescriptorQueryToken queryDescriptorToken)
        {
            ExceptionUtils.CheckArgumentNotNull(queryDescriptorToken, "queryDescriptorToken");
            ExceptionUtils.CheckArgumentNotNull(queryDescriptorToken.Path, "queryDescriptorToken.Path");

            // Make a copy of query options since we may consume some of them as we bind the query
            this.queryOptions = new List<QueryOptionQueryToken>(queryDescriptorToken.QueryOptions);
            //// TODO: check whether there is a $count segment at the top; if so strip it and first process everything else and
            ////       then add it to the bound query tree at the end

            // First bind the path
            QueryNode query = this.Bind(queryDescriptorToken.Path);

            // Apply filter first, then order-by, skip, top, select and expand
            query = this.ProcessFilter(query, queryDescriptorToken.Filter);
            query = this.ProcessOrderBy(query, queryDescriptorToken.OrderByTokens);
            query = ProcessSkip(query, queryDescriptorToken.Skip);
            query = ProcessTop(query, queryDescriptorToken.Top);

            //// TODO: if we found a $count segment process it now and add it to the query

            QueryDescriptorQueryNode queryDescriptorNode = new QueryDescriptorQueryNode();
            queryDescriptorNode.Query = query;

            // Add the remaining query options to the query descriptor.
            List<QueryNode> boundQueryOptions = this.ProcessQueryOptions();
            queryDescriptorNode.CustomQueryOptions = new ReadOnlyCollection<QueryNode>(boundQueryOptions);
            Debug.Assert(this.queryOptions == null, "this.queryOptions == null");

            return queryDescriptorNode;
        }
Пример #8
0
 /// <summary>
 /// Create a new Uri builder for the given token.
 /// </summary>
 /// <param name="queryToken">The token to write out as Uri.</param>
 protected ODataUriBuilder(QueryDescriptorQueryToken queryToken)
 {
     this.queryToken = queryToken;
 }
Пример #9
0
        /// <summary>
        /// Write the descriptor token as URI part to this builder.
        /// </summary>
        /// <param name="queryDescriptor">To write as URI part.</param>
        public virtual void WriteQueryDescriptor(QueryDescriptorQueryToken queryDescriptor)
        {
            ExceptionUtils.CheckArgumentNotNull(queryDescriptor, "queryDescriptor");

            this.WriteQuery(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.Properties.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 (QueryOptionQueryToken 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());
            }
        }
        /// <summary>
        /// Parses the <paramref name="queryUri"/> and returns a new instance of <see cref="QueryDescriptorQueryToken"/>
        /// describing the query specified by the uri.
        /// </summary>
        /// <param name="queryUri">The absolute URI which holds the query to parse. This must be a path relative to the <paramref name="serviceBaseUri"/>.</param>
        /// <param name="serviceBaseUri">The base URI of the service.</param>
        /// <param name="maxDepth">The maximum depth of any single query part. Security setting to guard against DoS attacks causing stack overflows and such.</param>
        /// <returns>A new instance of <see cref="QueryDescriptorQueryToken"/> which represents the query specified in the <paramref name="queryUri"/>.</returns>
        public static QueryDescriptorQueryToken ParseUri(Uri queryUri, Uri serviceBaseUri, int maxDepth)
        {
            ExceptionUtils.CheckArgumentNotNull(queryUri, "queryUri");
            if (!queryUri.IsAbsoluteUri)
            {
                throw new ArgumentException(Strings.QueryDescriptorQueryToken_UriMustBeAbsolute(queryUri), "queryUri");
            }

            ExceptionUtils.CheckArgumentNotNull(serviceBaseUri, "serviceBaseUri");
            if (!serviceBaseUri.IsAbsoluteUri)
            {
                throw new ArgumentException(Strings.QueryDescriptorQueryToken_UriMustBeAbsolute(serviceBaseUri), "serviceBaseUri");
            }

            if (maxDepth <= 0)
            {
                throw new ArgumentException(Strings.QueryDescriptorQueryToken_MaxDepthInvalid, "maxDepth");
            }

            QueryDescriptorQueryToken queryDescriptor = new QueryDescriptorQueryToken();

            UriQueryPathParser pathParser = new UriQueryPathParser(maxDepth);

            queryDescriptor.Path = pathParser.ParseUri(queryUri, serviceBaseUri);

            List <QueryOptionQueryToken> queryOptions = HttpUtils.ParseQueryOptions(queryUri);

            string filter = queryOptions.GetQueryOptionValueAndRemove(UriQueryConstants.FilterQueryOption);

            if (filter != null)
            {
                UriQueryExpressionParser expressionParser = new UriQueryExpressionParser(maxDepth);
                queryDescriptor.Filter = expressionParser.ParseFilter(filter);
            }

            string orderBy = queryOptions.GetQueryOptionValueAndRemove(UriQueryConstants.OrderByQueryOption);

            if (orderBy != null)
            {
                UriQueryExpressionParser expressionParser = new UriQueryExpressionParser(maxDepth);
                queryDescriptor.OrderByTokens = expressionParser.ParseOrderBy(orderBy);
            }

            string skip = queryOptions.GetQueryOptionValueAndRemove(UriQueryConstants.SkipQueryOption);

            if (skip != null)
            {
                int skipValue;
                if (!UriPrimitiveTypeParser.TryUriStringToNonNegativeInteger(skip, out skipValue))
                {
                    throw new ODataException(Strings.QueryDescriptorQueryToken_InvalidSkipQueryOptionValue(skip));
                }

                queryDescriptor.Skip = skipValue;
            }

            string top = queryOptions.GetQueryOptionValueAndRemove(UriQueryConstants.TopQueryOption);

            if (top != null)
            {
                int topValue;
                if (!UriPrimitiveTypeParser.TryUriStringToNonNegativeInteger(top, out topValue))
                {
                    throw new ODataException(Strings.QueryDescriptorQueryToken_InvalidTopQueryOptionValue(top));
                }

                queryDescriptor.Top = topValue;
            }

            // the remaining query options are stored on the query descriptor
            queryDescriptor.QueryOptions = queryOptions.Count == 0 ? null : new ReadOnlyCollection <QueryOptionQueryToken>(queryOptions);

            return(queryDescriptor);
        }
Пример #11
0
 /// <summary>
 /// Create a new Uri builder for the given token.
 /// </summary>
 /// <param name="queryToken">The token to write out as Uri.</param>
 protected ODataUriBuilder(QueryDescriptorQueryToken queryToken)
 {
     this.queryToken = queryToken;
 }
Пример #12
0
        /// <summary>
        /// Write the descriptor token as URI part to this builder.
        /// </summary>
        /// <param name="queryDescriptor">To write as URI part.</param>
        public virtual void WriteQueryDescriptor(QueryDescriptorQueryToken queryDescriptor)
        {
            ExceptionUtils.CheckArgumentNotNull(queryDescriptor, "queryDescriptor");

            this.WriteQuery(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.Properties.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 (QueryOptionQueryToken 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());
            }
        }
        /// <summary>
        /// Parses the <paramref name="queryUri"/> and returns a new instance of <see cref="QueryDescriptorQueryToken"/>
        /// describing the query specified by the uri.
        /// </summary>
        /// <param name="queryUri">The absolute URI which holds the query to parse. This must be a path relative to the <paramref name="serviceBaseUri"/>.</param>
        /// <param name="serviceBaseUri">The base URI of the service.</param>
        /// <param name="maxDepth">The maximum depth of any single query part. Security setting to guard against DoS attacks causing stack overflows and such.</param>
        /// <returns>A new instance of <see cref="QueryDescriptorQueryToken"/> which represents the query specified in the <paramref name="queryUri"/>.</returns>
        public static QueryDescriptorQueryToken ParseUri(Uri queryUri, Uri serviceBaseUri, int maxDepth)
        {
            ExceptionUtils.CheckArgumentNotNull(queryUri, "queryUri");
            if (!queryUri.IsAbsoluteUri)
            {
                throw new ArgumentException(Strings.QueryDescriptorQueryToken_UriMustBeAbsolute(queryUri), "queryUri");
            }

            ExceptionUtils.CheckArgumentNotNull(serviceBaseUri, "serviceBaseUri");
            if (!serviceBaseUri.IsAbsoluteUri)
            {
                throw new ArgumentException(Strings.QueryDescriptorQueryToken_UriMustBeAbsolute(serviceBaseUri), "serviceBaseUri");
            }

            if (maxDepth <= 0)
            {
                throw new ArgumentException(Strings.QueryDescriptorQueryToken_MaxDepthInvalid, "maxDepth");
            }

            QueryDescriptorQueryToken queryDescriptor = new QueryDescriptorQueryToken();

            UriQueryPathParser pathParser = new UriQueryPathParser(maxDepth);
            queryDescriptor.Path = pathParser.ParseUri(queryUri, serviceBaseUri);

            List<QueryOptionQueryToken> queryOptions = HttpUtils.ParseQueryOptions(queryUri);

            string filter = queryOptions.GetQueryOptionValueAndRemove(UriQueryConstants.FilterQueryOption);
            if (filter != null)
            {
                UriQueryExpressionParser expressionParser = new UriQueryExpressionParser(maxDepth);
                queryDescriptor.Filter = expressionParser.ParseFilter(filter);
            }

            string orderBy = queryOptions.GetQueryOptionValueAndRemove(UriQueryConstants.OrderByQueryOption);
            if (orderBy != null)
            {
                UriQueryExpressionParser expressionParser = new UriQueryExpressionParser(maxDepth);
                queryDescriptor.OrderByTokens = expressionParser.ParseOrderBy(orderBy);
            }

            string skip = queryOptions.GetQueryOptionValueAndRemove(UriQueryConstants.SkipQueryOption);
            if (skip != null)
            {
                int skipValue;
                if (!UriPrimitiveTypeParser.TryUriStringToNonNegativeInteger(skip, out skipValue))
                {
                    throw new ODataException(Strings.QueryDescriptorQueryToken_InvalidSkipQueryOptionValue(skip));
                }

                queryDescriptor.Skip = skipValue;
            }

            string top = queryOptions.GetQueryOptionValueAndRemove(UriQueryConstants.TopQueryOption);
            if (top != null)
            {
                int topValue;
                if (!UriPrimitiveTypeParser.TryUriStringToNonNegativeInteger(top, out topValue))
                {
                    throw new ODataException(Strings.QueryDescriptorQueryToken_InvalidTopQueryOptionValue(top));
                }

                queryDescriptor.Top = topValue;
            }

            // the remaining query options are stored on the query descriptor
            queryDescriptor.QueryOptions = queryOptions.Count == 0 ? null : new ReadOnlyCollection<QueryOptionQueryToken>(queryOptions);

            return queryDescriptor;
        }