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; } }
private Uri GetNextPageLink(SparqlModel originalQueryModel) { if (!originalQueryModel.Limit.HasValue) { // No limit in the original query so there should be no next page return(null); } if (!originalQueryModel.OriginalLimit.HasValue || originalQueryModel.OriginalLimit.Value > originalQueryModel.Limit.Value) { // We need a next page link var thisPageLink = _request.Url.ToString(); var queryParams = System.Web.HttpUtility.ParseQueryString(_request.Url.Query); int nextPageStart = originalQueryModel.Offset.HasValue ? originalQueryModel.Offset.Value + originalQueryModel.Limit.Value : originalQueryModel.Limit.Value; queryParams["$skip"] = nextPageStart.ToString(CultureInfo.InvariantCulture); string updatedQuery = "?" + String.Join("&", queryParams.AllKeys.Select( k => String.Format("{0}={1}", k, queryParams[k]))); return(new Uri(_request.Url, updatedQuery)); } return(null); }
/// <summary> /// Creates an OData feed response containing a list of entries for a particular type of entity /// </summary> /// <param name="resultsGraph">The RDF graph containing the SPARQL results</param> /// <param name="entityType">The fully qualified domain name for the type of entity to be written</param> /// <param name="resultsCount">The count of the total number of results that the server can provide</param> /// <param name="originalQueryModel">The SPARQL query that was executed to generate this graph</param> public void CreateFeedFromGraph(IGraph resultsGraph, string entityType, int resultsCount, SparqlModel originalQueryModel = null) { var msgWriter = new ODataMessageWriter(_response, _writerSettings, _map.Model); var feedWriter = msgWriter.CreateODataFeedWriter(); var entries = new List<ODataEntry>(); var typeUri = _map.GetUriForType(entityType); if (!String.IsNullOrEmpty(typeUri)) { var predNode = resultsGraph.CreateUriNode(UriFactory.Create(RdfConstants.RdfType)); var objNode = resultsGraph.CreateUriNode(UriFactory.Create(typeUri)); if (originalQueryModel == null || originalQueryModel.Ordering == null) { // No sorting required, just iterate all instances foreach (var instanceTriple in resultsGraph.GetTriplesWithPredicateObject(predNode, objNode)) { var instanceUri = (instanceTriple.Subject as IUriNode).Uri; entries.Add(CreateODataEntry(resultsGraph, instanceUri.ToString(), entityType)); } } else { // We need to apply the same sort criteria to this graph to ensure // that the ODATA results are properly sorted. // NOTE: This will only work if all the properties used in the original query // are present in the graph - this could be a problem with more complex traversals // and the query may instead need to be rewritten / regenerated to extract only // the required sort properties. originalQueryModel.IsDescribe = false; var resultsTable = resultsGraph.ExecuteQuery(originalQueryModel.GetSparqlRepresentation()) as SparqlResultSet; var targetVariable= originalQueryModel.SelectVariables[0]; foreach (var result in resultsTable.Results) { var instanceUriNode = result[targetVariable] as IUriNode; if (instanceUriNode != null) { entries.Add(CreateODataEntry(resultsGraph, instanceUriNode.Uri.ToString(), entityType)); } } } } var feed = new ODataFeed {Id = _baseUri + _map.GetTypeSet(entityType)}; if (_writerSettings.Version >= ODataVersion.V2) { feed.Count = resultsCount; } if (originalQueryModel != null) { feed.NextPageLink = GetNextPageLink(originalQueryModel); } feedWriter.WriteStart(feed); foreach (var entry in entries) { feedWriter.WriteStart(entry); feedWriter.WriteEnd(); } feedWriter.WriteEnd(); feedWriter.Flush(); }
private Uri GetNextPageLink(SparqlModel originalQueryModel) { if (!originalQueryModel.Limit.HasValue) { // No limit in the original query so there should be no next page return null; } if (!originalQueryModel.OriginalLimit.HasValue || originalQueryModel.OriginalLimit.Value > originalQueryModel.Limit.Value) { // We need a next page link var thisPageLink = _request.Url.ToString(); var queryParams = System.Web.HttpUtility.ParseQueryString(_request.Url.Query); int nextPageStart = originalQueryModel.Offset.HasValue ? originalQueryModel.Offset.Value + originalQueryModel.Limit.Value : originalQueryModel.Limit.Value; queryParams["$skip"] = nextPageStart.ToString(CultureInfo.InvariantCulture); string updatedQuery = "?" + String.Join("&", queryParams.AllKeys.Select( k => String.Format("{0}={1}", k, queryParams[k]))); return new Uri(_request.Url, updatedQuery); } return null; }
/// <summary> /// Creates an OData feed response containing a list of entries for a particular type of entity /// </summary> /// <param name="resultsGraph">The RDF graph containing the SPARQL results</param> /// <param name="entityType">The fully qualified domain name for the type of entity to be written</param> /// <param name="resultsCount">The count of the total number of results that the server can provide</param> /// <param name="originalQueryModel">The SPARQL query that was executed to generate this graph</param> public void CreateFeedFromGraph(IGraph resultsGraph, string entityType, int resultsCount, SparqlModel originalQueryModel = null) { var msgWriter = new ODataMessageWriter(_response, _writerSettings, _map.Model); var feedWriter = msgWriter.CreateODataFeedWriter(); var entries = new List <ODataEntry>(); var typeUri = _map.GetUriForType(entityType); if (!String.IsNullOrEmpty(typeUri)) { var predNode = resultsGraph.CreateUriNode(UriFactory.Create(RdfConstants.RdfType)); var objNode = resultsGraph.CreateUriNode(UriFactory.Create(typeUri)); if (originalQueryModel == null || originalQueryModel.Ordering == null) { // No sorting required, just iterate all instances foreach (var instanceTriple in resultsGraph.GetTriplesWithPredicateObject(predNode, objNode)) { var instanceUri = (instanceTriple.Subject as IUriNode).Uri; entries.Add(CreateODataEntry(resultsGraph, instanceUri.ToString(), entityType)); } } else { // We need to apply the same sort criteria to this graph to ensure // that the ODATA results are properly sorted. // NOTE: This will only work if all the properties used in the original query // are present in the graph - this could be a problem with more complex traversals // and the query may instead need to be rewritten / regenerated to extract only // the required sort properties. originalQueryModel.IsDescribe = false; var resultsTable = resultsGraph.ExecuteQuery(originalQueryModel.GetSparqlRepresentation()) as SparqlResultSet; var targetVariable = originalQueryModel.SelectVariables[0]; foreach (var result in resultsTable.Results) { var instanceUriNode = result[targetVariable] as IUriNode; if (instanceUriNode != null) { entries.Add(CreateODataEntry(resultsGraph, instanceUriNode.Uri.ToString(), entityType)); } } } } var feed = new ODataFeed { Id = _baseUri + _map.GetTypeSet(entityType) }; if (_writerSettings.Version >= ODataVersion.V2) { feed.Count = resultsCount; } if (originalQueryModel != null) { feed.NextPageLink = GetNextPageLink(originalQueryModel); } feedWriter.WriteStart(feed); foreach (var entry in entries) { feedWriter.WriteStart(entry); feedWriter.WriteEnd(); } feedWriter.WriteEnd(); feedWriter.Flush(); }