예제 #1
0
        public void TestRetrieveSingleFilm()
        {
            const string odataQuery  = "http://example.org/odata/Films('Un_Chien_Andalou')";
            var          parsedQuery = QueryDescriptorQueryNode.ParseUri(
                new Uri(odataQuery), new Uri(_odataBase), _dbpediaModel);
            var sparqlGenerator = new SparqlGenerator(_dbpediaMap);

            sparqlGenerator.ProcessQuery(parsedQuery);
            Console.WriteLine(sparqlGenerator.SparqlQueryModel.GetSparqlRepresentation());
            var mockRequest = new Mock <IODataRequestMessage>();

            mockRequest.Setup(m => m.Url).Returns(new Uri(odataQuery));
            var mockMessage  = new Mock <IODataResponseMessage>();
            var outputStream = new MemoryStream();

            mockMessage.Setup(m => m.GetStream()).Returns(outputStream);
            var feedGenerator = new ODataFeedGenerator(mockRequest.Object, mockMessage.Object, _dbpediaMap, _odataBase, new ODataMessageWriterSettings {
                Indent = true
            });

            sparqlGenerator.SparqlQueryModel.Execute(_sparqlEndpoint, feedGenerator);
            outputStream.Seek(0, SeekOrigin.Begin);
            var validator = new XPathValidator(outputStream);

            validator.AddNamespace("atom", "http://www.w3.org/2005/Atom");
            validator.AddNamespace("d", "http://schemas.microsoft.com/ado/2007/08/dataservices");
            validator.AddNamespace("m", "http://schemas.microsoft.com/ado/2007/08/dataservices/metadata");
            Console.WriteLine(validator.ToString());
            validator.AssertRoot("atom:entry");
            validator.AssertXPathValue("/atom:entry/atom:id", "http://example.org/odata/Films('Un_Chien_Andalou')");
            validator.AssertXPathValue("/atom:entry/atom:title", "");
            validator.AssertXPathValue("/atom:entry/atom:content/m:properties/d:Name", "Un Chien Andalou");
            validator.AssertXPathValue("/atom:entry/atom:content/m:properties/d:Runtime", "960.0");
            validator.AssertXPathValue("/atom:entry/atom:link[@rel='http://schemas.microsoft.com/ado/2007/08/dataservices/related/Director']/@href", "http://example.org/odata/Films('Un_Chien_Andalou')/Director");
        }
예제 #2
0
        private XPathValidator GenerateAndExecuteSparql(string odataQuery, SparqlMap sparqlMap, ODataVersion odataVersion = ODataVersion.V3)
        {
            var parsedQuery = QueryDescriptorQueryNode.ParseUri(
                new Uri(odataQuery),
                new Uri(_odataBase),
                _dbpediaModel);
            var sparqlGenerator = new SparqlGenerator(sparqlMap, "en");

            sparqlGenerator.ProcessQuery(parsedQuery);
            var mockRequest = new Mock <IODataRequestMessage>();

            mockRequest.Setup(m => m.Url).Returns(new Uri(odataQuery));
            var mockMessage  = new Mock <IODataResponseMessage>();
            var outputStream = new MemoryStream();

            mockMessage.Setup(m => m.GetStream()).Returns(outputStream);
            var feedGenerator = new ODataFeedGenerator(
                mockRequest.Object,
                mockMessage.Object, sparqlMap, _odataBase,
                new ODataMessageWriterSettings {
                Indent = true, Version = odataVersion
            });

            Console.WriteLine(sparqlGenerator.SparqlQueryModel.GetSparqlRepresentation());
            sparqlGenerator.SparqlQueryModel.Execute(_sparqlEndpoint, feedGenerator);
            outputStream.Seek(0, SeekOrigin.Begin);
            var validator = new XPathValidator(outputStream);

            validator.AddNamespace("atom", "http://www.w3.org/2005/Atom");
            validator.AddNamespace("d", "http://schemas.microsoft.com/ado/2007/08/dataservices");
            validator.AddNamespace("m", "http://schemas.microsoft.com/ado/2007/08/dataservices/metadata");
            return(validator);
        }
예제 #3
0
        // Not implemented yet because the OData parser library does not support isof
        //[TestMethod]
        //public void TestFnIsOf()
        //{
        //    var sparql = ProcessQuery("http://example.org/odata/Works?$filter=isof('DBPedia.Film')");
        //    Assert.IsNotNull(sparql);
        //    Console.WriteLine(sparql);
        //    Assert.AreEqual(1, sparql.RootGraphPattern.FilterExpressions.Count);
        //    Assert.AreEqual("EXISTS {?v1 a <http://dbpedia.org/ontology/Work>}", sparql.RootGraphPattern.FilterExpressions[0]);
        //}



        // Not implemented yet because the OData parser library does not support $select or $expand
        //[TestMethod]
        //public void TestSelectSimpleProperties()
        //{
        //    var sparql = ProcessQuery("http://example.org/odata/Films?$select=Name,Runtime,ReleaseDate");
        //    Assert.IsNotNull(sparql);
        //    Console.WriteLine(sparql.GetSparqlRepresentation());
        //    Assert.IsFalse(sparql.IsDescribe);
        //}

        private SparqlModel ProcessQuery(string odataQuery)
        {
            var generator       = new SparqlGenerator(_dbpediaMap);
            var queryDescriptor = QueryDescriptorQueryNode.ParseUri(
                new Uri(odataQuery),
                new Uri("http://example.org/odata/"), _dbpediaModel);

            generator.ProcessQuery(queryDescriptor);
            return(generator.SparqlQueryModel);
        }
예제 #4
0
        public void TestBindInstanceAccess()
        {
            var queryDescriptor = QueryDescriptorQueryNode.ParseUri(
                new Uri("http://example.org/odata/Films('Un_Chien_Andalou')"),
                new Uri("http://example.org/odata/"),
                _dbpediaModel);

            Assert.IsNotNull(queryDescriptor);
            Assert.IsNotNull(queryDescriptor.Query);
            Assert.AreEqual(QueryNodeKind.KeyLookup, queryDescriptor.Query.Kind);
        }
예제 #5
0
        public void TestInstanceAccess()
        {
            var dbpediaGenerator = new SparqlGenerator(_dbpediaMap);
            var queryDescriptor  = QueryDescriptorQueryNode.ParseUri(
                new Uri("http://example.org/odata/Films('Un_Chien_Andalou')"),
                new Uri("http://example.org/odata/"), _dbpediaModel);

            dbpediaGenerator.ProcessQuery(queryDescriptor);
            Assert.IsNotNull(dbpediaGenerator.SparqlQueryModel);
            Assert.IsNotNull(dbpediaGenerator.SparqlQueryModel.DescribeResource);
            Assert.AreEqual("http://dbpedia.org/resource/Un_Chien_Andalou", dbpediaGenerator.SparqlQueryModel.DescribeResource);
            Assert.AreEqual("DBPedia.Film", dbpediaGenerator.SparqlQueryModel.GetEntityType("http://dbpedia.org/resource/Un_Chien_Andalou"));
        }
예제 #6
0
        public void TestSkip()
        {
            var generator       = new SparqlGenerator(_dbpediaMap);
            var queryDescriptor = QueryDescriptorQueryNode.ParseUri(
                new Uri("http://example.org/odata/Films?$skip=5"),
                new Uri("http://example.org/odata/"), _dbpediaModel);

            generator.ProcessQuery(queryDescriptor);
            var sparql = generator.SparqlQueryModel;

            Assert.IsNotNull(sparql);
            Assert.IsTrue(sparql.IsDescribe);
            Assert.AreEqual(5, sparql.Offset);
        }
예제 #7
0
        public void TestBindTypeSetAccess()
        {
            var queryDescriptor = QueryDescriptorQueryNode.ParseUri(
                new Uri("http://example.org/odata/Films"),
                new Uri("http://example.org/odata/"), _dbpediaModel);

            Assert.IsNotNull(queryDescriptor);
            Assert.IsNotNull(queryDescriptor.Query);
            Assert.AreEqual(QueryNodeKind.EntitySet, queryDescriptor.Query.Kind);
            var entitySetQueryNode = queryDescriptor.Query as EntitySetQueryNode;

            Assert.IsNotNull(entitySetQueryNode);
            Assert.AreEqual("Films", entitySetQueryNode.EntitySet.Name);
            Assert.AreEqual("DBPedia.Film", entitySetQueryNode.ItemType.FullName());
        }
예제 #8
0
        public void ProcessQuery(QueryDescriptorQueryNode query)
        {
            _sparqlModel = new SparqlModel();
            switch (query.Query.Kind)
            {
            case QueryNodeKind.EntitySet:
                ProcessNode(query.Query as EntitySetQueryNode);
                break;

            case QueryNodeKind.KeyLookup:
                ProcessRoot(query.Query as KeyLookupQueryNode);
                break;

            case QueryNodeKind.Filter:
                var entityType = (query.Query as FilterQueryNode).ItemType;
                var instances  = AssertInstancesVariable(entityType);
                _entitySetVariable = instances;
                ProcessFilter(query.Query as FilterQueryNode);
                _sparqlModel.AddSelectVariable(instances, entityType.FullName(), true);
                _sparqlModel.IsDescribe = true;
                break;

            case QueryNodeKind.Top:
            case QueryNodeKind.Skip:
                ProcessNode(query.Query);
                break;

            case QueryNodeKind.Segment:
                var navigation = query.Query as NavigationPropertyNode;
                var finalVar   = ProcessNode(navigation);
                _sparqlModel.AddSelectVariable(
                    finalVar.ToString(),
                    navigation.TypeReference.FullName(),
                    navigation.NavigationProperty.OwnMultiplicity() == EdmMultiplicity.Many);
                _sparqlModel.IsDescribe = true;
                break;

            default:
                throw new NotImplementedException("No processing implemented for " + query.Query.Kind);
            }

            // Apply page size limit
            if (!_sparqlModel.Limit.HasValue || _sparqlModel.Limit.Value > _maxPageSize)
            {
                _sparqlModel.OriginalLimit = _sparqlModel.Limit;
                _sparqlModel.Limit         = _maxPageSize;
            }
        }
예제 #9
0
        public void TestSkipAndTop()
        {
            var generator       = new SparqlGenerator(_dbpediaMap);
            var queryDescriptor = QueryDescriptorQueryNode.ParseUri(
                new Uri("http://example.org/odata/Films?$skip=50&$top=10"),
                new Uri("http://example.org/odata/"),
                _dbpediaModel);

            generator.ProcessQuery(queryDescriptor);
            var sparql = generator.SparqlQueryModel;

            Assert.IsNotNull(sparql);
            Assert.IsTrue(sparql.IsDescribe);
            Assert.AreEqual(1, sparql.RootGraphPattern.TriplePatterns.Count);
            Assert.AreEqual(10, sparql.Limit);
            Assert.AreEqual(50, sparql.Offset);
        }
예제 #10
0
        public void TestOrderByProperty()
        {
            var generator       = new SparqlGenerator(_dbpediaMap);
            var queryDescriptor = QueryDescriptorQueryNode.ParseUri(
                new Uri("http://example.org/odata/Places?$orderby=PopulationTotal&$top=20"),
                new Uri("http://example.org/odata/"), _dbpediaModel);

            generator.ProcessQuery(queryDescriptor);
            var sparql = generator.SparqlQueryModel;

            Assert.IsNotNull(sparql);
            Assert.IsTrue(sparql.IsDescribe);
            Assert.AreEqual(20, sparql.Limit);
            Assert.IsNotNull(sparql.Ordering);
            Assert.IsTrue(sparql.Ordering.IsSimple);
            Assert.AreEqual("v2", sparql.Ordering.Variable);
            Assert.IsNull(sparql.Ordering.ThenBy);
        }
예제 #11
0
        public void ProcessQuery(QueryDescriptorQueryNode query)
        {
            _sparqlModel = new SparqlModel();
            switch (query.Query.Kind)
            {
                case QueryNodeKind.EntitySet:
                    ProcessNode(query.Query as EntitySetQueryNode);
                    break;
                case QueryNodeKind.KeyLookup:
                    ProcessRoot(query.Query as KeyLookupQueryNode);
                    break;
                case QueryNodeKind.Filter:
                    var entityType = (query.Query as FilterQueryNode).ItemType;
                    var instances = AssertInstancesVariable(entityType);
                    _entitySetVariable = instances;
                    ProcessFilter(query.Query as FilterQueryNode);
                    _sparqlModel.AddSelectVariable(instances, entityType.FullName(), true);
                    _sparqlModel.IsDescribe = true;
                    break;
                case QueryNodeKind.Top:
                case QueryNodeKind.Skip:
                    ProcessNode(query.Query);
                    break;
                case QueryNodeKind.Segment:
                    var navigation = query.Query as NavigationPropertyNode;
                    var finalVar = ProcessNode(navigation);
                    _sparqlModel.AddSelectVariable(
                        finalVar.ToString(), 
                        navigation.TypeReference.FullName(),
                        navigation.NavigationProperty.OwnMultiplicity() == EdmMultiplicity.Many);
                    _sparqlModel.IsDescribe = true;
                    break;
                default:
                    throw new NotImplementedException("No processing implemented for " + query.Query.Kind);
            }

            // Apply page size limit
            if (!_sparqlModel.Limit.HasValue || _sparqlModel.Limit.Value > _maxPageSize)
            {
                _sparqlModel.OriginalLimit = _sparqlModel.Limit;
                _sparqlModel.Limit = _maxPageSize;
            }
        }
예제 #12
0
        public void TestEntitySetAccess()
        {
            var dbpediaGenerator = new SparqlGenerator(_dbpediaMap);
            var queryDescriptor  = QueryDescriptorQueryNode.ParseUri(
                new Uri("http://example.org/odata/Films"),
                new Uri("http://example.org/odata/"), _dbpediaModel);

            dbpediaGenerator.ProcessQuery(queryDescriptor);
            Assert.IsNotNull(dbpediaGenerator.SparqlQueryModel);
            Assert.IsNotNull(dbpediaGenerator.SparqlQueryModel.RootGraphPattern);
            Assert.AreEqual(1, dbpediaGenerator.SparqlQueryModel.RootGraphPattern.TriplePatterns.Count);
            var tp = dbpediaGenerator.SparqlQueryModel.RootGraphPattern.TriplePatterns[0];

            Assert.AreEqual("?v1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://dbpedia.org/ontology/Film>",
                            tp.GetSparqlRepresentation());
            Assert.IsNotNull(dbpediaGenerator.SparqlQueryModel.SelectVariables);
            Assert.AreEqual(1, dbpediaGenerator.SparqlQueryModel.SelectVariables.Count);
            Assert.IsTrue(dbpediaGenerator.SparqlQueryModel.SelectVariables.Contains("v1"));
            Assert.IsTrue(dbpediaGenerator.SparqlQueryModel.IsDescribe);
            Assert.AreEqual("DBPedia.Film", dbpediaGenerator.SparqlQueryModel.GetEntityType("v1"));
        }
예제 #13
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;
        }
예제 #14
0
        public void ProcessRequest(HttpContext context, Uri serviceBaseUri)
        {
            var sparqlGenerator = new SparqlGenerator(_config.Map, _config.DefaultLanguageCode, _config.MaxPageSize);

            var messageWriterSettings = new ODataMessageWriterSettings(_config.BaseODataWriterSettings)
            {
                BaseUri = serviceBaseUri
            };

            if (context.Request.AcceptTypes != null)
            {
                messageWriterSettings.SetContentType(String.Join(",", context.Request.AcceptTypes),
                                                     context.Request.Headers["Accept-Charset"]);
            }

            var          requestMessage   = new HttpDataRequestMessage(context.Request);
            ODataVersion effectiveVersion = GetEffectiveODataVersion(requestMessage);

            messageWriterSettings.Version = effectiveVersion;

            var metadataUri = new Uri(serviceBaseUri, "./$metadata");

            if (serviceBaseUri.Equals(context.Request.Url))
            {
                // We need to respond with the service document
                var responseMessage = new HttpDataResponseMessage(context.Response);
                context.Response.ContentType     = "application/xml";
                context.Response.ContentEncoding = System.Text.Encoding.UTF8;
                var feedGenerator = new ODataFeedGenerator(requestMessage, responseMessage,
                                                           _config.Map, serviceBaseUri.ToString(),
                                                           messageWriterSettings);
                feedGenerator.WriteServiceDocument();
            }
            else if (serviceBaseUri.ToString().TrimEnd('/').Equals(context.Request.Url.ToString().TrimEnd('/')))
            {
                // Trimming of trailing slash to normalize - the serviceBaseUri should always have a trailing slash,
                // but we will redirect requests that do not to the proper service document url
                context.Response.RedirectPermanent(serviceBaseUri.ToString(), true);
            }
            else if (metadataUri.Equals(context.Request.Url))
            {
                context.Response.ContentType = "application/xml";
                context.Response.WriteFile(_config.MetadataPath);
            }
            else
            {
                var parsedQuery = QueryDescriptorQueryNode.ParseUri(
                    context.Request.Url,
                    serviceBaseUri,
                    _config.Model);
                sparqlGenerator.ProcessQuery(parsedQuery);
                var responseMessage = new HttpDataResponseMessage(context.Response);
                var feedGenerator   = new ODataFeedGenerator(
                    requestMessage,
                    responseMessage,
                    _config.Map,
                    serviceBaseUri.ToString(),
                    messageWriterSettings);
                sparqlGenerator.SparqlQueryModel.Execute(_config.SparqlEndpoint, feedGenerator);
                context.Response.ContentType = "application/atom+xml";
            }
        }