/// <summary> /// Parser method which parses a Binding Object which occurs in the array of Bindings /// </summary> private void ParseBinding(SparqlJsonParserContext context, bool headSeen) { //Can we read some properties if (context.Input.Read()) { SparqlResult result = new SparqlResult(); while (context.Input.TokenType != JsonToken.EndObject) { if (context.Input.TokenType == JsonToken.PropertyName) { //Each Property Name should be for a variable this.ParseBoundVariable(context, context.Input.Value.ToString(), result, headSeen); } else { throw Error(context, "Unexpected Token '" + context.Input.TokenType + "' with value '" + context.Input.Value + "' encountered, expected a Property Name giving the Binding for a Variable for this Result"); } //Get Next Token if (!context.Input.Read()) { throw new RdfParseException("Unexpected End of Input while trying to parse a Binding Object"); } } //Check that all Variables are bound for a given result binding nulls where appropriate foreach (String v in context.Variables) { if (!result.HasValue(v)) { result.SetValue(v, null); } } //Add to Results result.SetVariableOrdering(context.Variables); if (!context.Handler.HandleResult(result)) { ParserHelper.Stop(); } } else { throw new RdfParseException("Unexpected End of Input while trying to parse a Binding Object"); } }
private void TryParseResultRow(TokenisingResultParserContext context) { IToken next = context.Tokens.Peek(); if (next.TokenType == Token.EOF) { context.Tokens.Dequeue(); return; } bool allowEOL = true, expectComma = false; int v = 0; SparqlResult result = new SparqlResult(); while (true) { next = context.Tokens.Dequeue(); switch (next.TokenType) { case Token.BLANKNODEWITHID: if (expectComma) throw ParserHelper.Error("Unexpected Blank Node, expected a comma between RDF Terms", next); if (v >= context.Variables.Count) throw ParserHelper.Error("Too many RDF Terms, only expecting " + context.Variables.Count + " terms", next); INode blank = context.Handler.CreateBlankNode(next.Value.Substring(2)); result.SetValue(context.Variables[v], blank); v++; allowEOL = true; expectComma = true; break; case Token.LITERAL: case Token.PLAINLITERAL: if (expectComma) throw ParserHelper.Error("Unexpected Blank Node, expected a comma between RDF Terms", next); if (v >= context.Variables.Count) throw ParserHelper.Error("Too many RDF Terms, only expecting " + context.Variables.Count + " terms", next); //Try and guess what kind of term this is String lexicalForm = next.Value; INode value; if (lexicalForm.StartsWith("http://") || lexicalForm.StartsWith("https://") || lexicalForm.StartsWith("mailto:") || lexicalForm.StartsWith("ftp://")) { try { //Guessing a URI if starts with common URI prefix value = context.Handler.CreateUriNode(UriFactory.Create(lexicalForm)); } catch { //If invalid URI fall back to treating as literal value = context.Handler.CreateLiteralNode(lexicalForm); } } else { value = context.Handler.CreateLiteralNode(lexicalForm); } result.SetValue(context.Variables[v], value); v++; allowEOL = true; expectComma = true; break; case Token.EOL: if (allowEOL) { break; } else { if (v == context.Variables.Count - 1) { //If this is the last expected term then this must be an empty term v++; break; } throw ParserHelper.Error("Unexpected End of Line, expected a RDF Term Token", next); } case Token.COMMA: if (!expectComma) { //This is an empty field if (v >= context.Variables.Count) throw ParserHelper.Error("Too many RDF Terms, only expecting " + context.Variables.Count + " terms", next); v++; } expectComma = false; allowEOL = false; break; case Token.EOF: if (!allowEOL) throw ParserHelper.Error("Unexpected EOF, expected another RDF Term for the Result Row", next); break; default: throw ParserHelper.Error("Unexpected Token '" + next.GetType().ToString() + "' encountered", next); } //Stop when we've hit the End of the Line/File if (next.TokenType == Token.EOL || next.TokenType == Token.EOF) break; } if (!context.Handler.HandleResult(result)) ParserHelper.Stop(); }
/// <summary> /// Internal method which actually parses the Result Set by traversing the RDF Graph appropriately /// </summary> /// <param name="context">Parser Context</param> private void Parse(SparqlRdfParserContext context) { try { context.Handler.StartResults(); //Create relevant Nodes context.Graph.NamespaceMap.AddNamespace("rdf", UriFactory.Create(NamespaceMapper.RDF)); context.Graph.NamespaceMap.AddNamespace("rs", UriFactory.Create(SparqlSpecsHelper.SparqlRdfResultsNamespace)); IUriNode rdfType = context.Graph.CreateUriNode("rdf:type"); IUriNode resultSetClass = context.Graph.CreateUriNode("rs:ResultSet"); IUriNode resultVariable = context.Graph.CreateUriNode("rs:resultVariable"); IUriNode solution = context.Graph.CreateUriNode("rs:solution"); IUriNode binding = context.Graph.CreateUriNode("rs:binding"); IUriNode value = context.Graph.CreateUriNode("rs:value"); IUriNode variable = context.Graph.CreateUriNode("rs:variable"); IUriNode boolean = context.Graph.CreateUriNode("rs:boolean"); //Try to get a ResultSet object Triple rset = context.Graph.Triples.WithPredicateObject(rdfType, resultSetClass).FirstOrDefault(); if (rset != null) { INode rsetID = rset.Subject; //Find the Variables the Result Set contains or the Boolean Value List <Triple> temp = context.Graph.Triples.WithSubjectPredicate(rsetID, boolean).ToList(); if (temp.Count > 0) { if (temp.Count > 1) { throw new RdfParseException("Result Set has more than one boolean result defined for it"); } Triple booleanResult = temp.First(); INode result = booleanResult.Object; if (result.NodeType == NodeType.Literal) { ILiteralNode lit = (ILiteralNode)result; if (lit.DataType != null) { if (lit.DataType.AbsoluteUri.Equals(XmlSpecsHelper.XmlSchemaDataTypeBoolean)) { bool b; if (Boolean.TryParse(lit.Value, out b)) { context.Handler.HandleBooleanResult(b); return; } else { throw new RdfParseException("Result Set has a boolean result which is a Literal typed as boolean but which does not contain a valid boolean value"); } } else { throw new RdfParseException("Result Set has a boolean result which is a Literal which is not boolean typed"); } } else { throw new RdfParseException("Result Set has a boolean result which is a Literal which is not typed as a boolean"); } } else { throw new RdfParseException("Result Set has a boolean result which is not a Literal Node"); } } else { //We're expected one/more variables temp = context.Graph.Triples.WithSubjectPredicate(rsetID, resultVariable).ToList(); if (temp.Count > 0) { foreach (Triple t in temp) { if (t.Object.NodeType == NodeType.Literal) { if (!context.Handler.HandleVariable(((ILiteralNode)t.Object).Value)) { ParserHelper.Stop(); } context.Variables.Add(((ILiteralNode)t.Object).Value); } else { throw new RdfParseException("Result Set has a result variable definition which is not a Literal Node"); } } } else { throw new RdfParseException("Result Set does not define any result variables or a boolean result"); } //Then we're expecting some Solutions temp = context.Graph.Triples.WithSubjectPredicate(rsetID, solution).ToList(); foreach (Triple slnTriple in temp) { //Each Solution has some Bindings INode slnID = slnTriple.Object; bool ok = false; SparqlResult r = new SparqlResult(); foreach (Triple bindingTriple in context.Graph.Triples.WithSubjectPredicate(slnID, binding)) { //Each Binding has a Variable and a Value ok = true; INode bindingID = bindingTriple.Object; String var = String.Empty; INode val = null; //Retrieve the Variable and the Bound Value foreach (Triple valueTriple in context.Graph.Triples.WithSubject(bindingID)) { if (valueTriple.Predicate.Equals(variable)) { if (!var.Equals(String.Empty)) { throw new RdfParseException("Result Set contains a Binding which refers to more than one Variable"); } if (valueTriple.Object.NodeType != NodeType.Literal) { throw new RdfParseException("Result Set contains a Binding which refers to a Variable but not by a Literal Node as required"); } var = ((ILiteralNode)valueTriple.Object).Value; } else if (valueTriple.Predicate.Equals(value)) { if (val != null) { throw new RdfParseException("Result Set contains a Binding which has more than one Value"); } val = valueTriple.Object; } } if (var.Equals(String.Empty) || val == null) { throw new RdfParseException("Result Set contains a Binding which doesn't contain both a Variable and a Value"); } //Check that the Variable was defined in the Header if (!context.Variables.Contains(var)) { throw new RdfParseException("Unable to Parse a SPARQL Result Set since a <binding> element attempts to bind a value to the variable '" + var + "' which is not defined in the <head> by a <variable> element!"); } r.SetValue(var, val); } if (!ok) { throw new RdfParseException("Result Set contains a Solution which has no Bindings"); } //Check that all Variables are bound for a given result binding nulls where appropriate foreach (String v in context.Variables) { if (!r.HasValue(v)) { r.SetValue(v, null); } } if (!context.Handler.HandleResult(r)) { ParserHelper.Stop(); } } } } else { throw new RdfParseException("No Result Set object is defined in the Graph"); } context.Handler.EndResults(true); } catch (RdfParsingTerminatedException) { context.Handler.EndResults(true); } catch { context.Handler.EndResults(false); throw; } }
private void TryParseResultRow(TokenisingResultParserContext context) { IToken next = context.Tokens.Peek(); if (next.TokenType == Token.EOF) { context.Tokens.Dequeue(); return; } bool allowEOL = true, expectTab = false; int v = 0; SparqlResult result = new SparqlResult(); while (true) { next = context.Tokens.Dequeue(); switch (next.TokenType) { case Token.URI: if (expectTab) throw ParserHelper.Error("Unexpected URI, expected a Tab between RDF Terms", next); if (v >= context.Variables.Count) throw ParserHelper.Error("Too many RDF Terms, only expecting " + context.Variables.Count + " terms", next); INode uri = ParserHelper.TryResolveUri(context, next); result.SetValue(context.Variables[v], uri); v++; allowEOL = true; expectTab = true; break; case Token.BLANKNODEWITHID: if (expectTab) throw ParserHelper.Error("Unexpected Blank Node, expected a Tab between RDF Terms", next); if (v >= context.Variables.Count) throw ParserHelper.Error("Too many RDF Terms, only expecting " + context.Variables.Count + " terms", next); INode blank = context.Handler.CreateBlankNode(next.Value.Substring(2)); result.SetValue(context.Variables[v], blank); v++; allowEOL = true; expectTab = true; break; case Token.LITERAL: case Token.LONGLITERAL: case Token.PLAINLITERAL: if (expectTab) throw ParserHelper.Error("Unexpected Blank Node, expected a Tab between RDF Terms", next); if (v >= context.Variables.Count) throw ParserHelper.Error("Too many RDF Terms, only expecting " + context.Variables.Count + " terms", next); INode lit = this.TryParseLiteral(context, next); result.SetValue(context.Variables[v], lit); v++; allowEOL = true; expectTab = true; break; case Token.EOL: if (allowEOL) { break; } else { if (v == context.Variables.Count - 1) { //If this is the last expected term then this must be an empty term v++; break; } throw ParserHelper.Error("Unexpected End of Line, expected a RDF Term Token", next); } case Token.TAB: if (!expectTab) { //This is an empty field if (v >= context.Variables.Count) throw ParserHelper.Error("Too many RDF Terms, only expecting " + context.Variables.Count + " terms", next); v++; } expectTab = false; allowEOL = false; break; case Token.EOF: if (!allowEOL) throw ParserHelper.Error("Unexpected EOF, expected another RDF Term for the Result Row", next); break; default: throw ParserHelper.Error("Unexpected Token '" + next.GetType().ToString() + "' encountered", next); } //Stop when we've hit the End of the Line/File if (next.TokenType == Token.EOL || next.TokenType == Token.EOF) break; } if (!context.Handler.HandleResult(result)) ParserHelper.Stop(); }
/// <summary> /// Parser method which parses a Bound Variable Object which occurs within a Binding Object /// </summary> /// <param name="context">Parser Context</param> /// <param name="var">Variable Name</param> /// <param name="r">Result Object that is being constructed from the Binding Object</param> private void ParseBoundVariable(SparqlJsonParserContext context, String var, SparqlResult r) { String token, nodeValue, nodeType, nodeLang, nodeDatatype; nodeValue = nodeType = nodeLang = nodeDatatype = null; //Can we read the start of an Object if (context.Input.Read()) { if (context.Input.TokenType == JsonToken.StartObject) { context.Input.Read(); while (context.Input.TokenType != JsonToken.EndObject) { token = context.Input.Value.ToString().ToLower(); //Check that we get a Property Value as a String context.Input.Read(); if (context.Input.TokenType != JsonToken.String) { throw Error(context, "Unexpected Token '" + context.Input.TokenType.ToString() + "' encountered, expected a Property Value describing one of the properties of an Variable Binding"); } //Extract the Information from the Object if (token.Equals("value")) { nodeValue = context.Input.Value.ToString(); } else if (token.Equals("type")) { nodeType = context.Input.Value.ToString().ToLower(); } else if (token.Equals("lang") || token.Equals("xml:lang")) { if (nodeLang == null && nodeDatatype == null) { nodeLang = context.Input.Value.ToString(); } else { throw Error(context, "Unexpected Language Property specified for an Object Node where a Language or Datatype has already been specified"); } } else if (token.Equals("datatype")) { if (nodeDatatype == null && nodeLang == null) { nodeDatatype = context.Input.Value.ToString(); } else { throw Error(context, "Unexpected Datatype Property specified for an Object Node where a Language or Datatype has already been specified"); } } else { throw Error(context, "Unexpected Property '" + token + "' specified for an Object Node, only 'value', 'type', 'lang' and 'datatype' are valid properties"); } //Get Next Token if (!context.Input.Read()) { throw new RdfParseException("Unexpected End of Input while trying to parse a Bound Variable Object"); } } //Validate the Information if (nodeType == null) { throw new RdfParseException("Cannot parse a Node from the JSON where no 'type' property was specified in the JSON Object representing the Node"); } if (nodeValue == null) { throw new RdfParseException("Cannot parse a Node from the JSON where no 'value' property was specified in the JSON Object representing the Node"); } //Turn this information into a Node INode n; if (nodeType.Equals("uri")) { n = context.Handler.CreateUriNode(new Uri(nodeValue)); } else if (nodeType.Equals("bnode")) { if (nodeValue.StartsWith("_:")) { n = context.Handler.CreateBlankNode(nodeValue.Substring(2)); } else if (nodeValue.Contains("://")) { n = context.Handler.CreateBlankNode(nodeValue.Substring(nodeValue.IndexOf("://") + 3)); } else if (nodeValue.Contains(":")) { n = context.Handler.CreateBlankNode(nodeValue.Substring(nodeValue.LastIndexOf(':') + 1)); } else { n = context.Handler.CreateBlankNode(nodeValue); } } else if (nodeType.Equals("literal") || nodeType.Equals("typed-literal")) { if (nodeLang != null) { n = context.Handler.CreateLiteralNode(nodeValue, nodeLang); } else if (nodeDatatype != null) { n = context.Handler.CreateLiteralNode(nodeValue, new Uri(nodeDatatype)); } else { n = context.Handler.CreateLiteralNode(nodeValue); } } else { throw new RdfParseException("Cannot parse a Node from the JSON where the 'type' property has a value of '" + nodeType + "' which is not one of the permitted values 'uri', 'bnode', 'literal' or 'typed-literal' in the JSON Object representing the Node"); } //Check that the Variable was defined in the Header if (!context.Variables.Contains(var)) { throw new RdfParseException("Unable to Parse a SPARQL Result Set since a Binding Object attempts to bind a value to the variable '" + var + "' which is not defined in the Header Object in the value for the 'vars' property!"); } //Add to the result r.SetValue(var, n); } else { throw Error(context, "Unexpected Token '" + context.Input.TokenType.ToString() + "' encountered, expected the start of a Bound Variable Object"); } } else { throw Error(context, "Unexpected End of Input while trying to parse a Bound Variable Object"); } }
/// <summary> /// Parser method which parses a Binding Object which occurs in the array of Bindings /// </summary> private void ParseBinding(SparqlJsonParserContext context) { //Can we read some properties if (context.Input.Read()) { SparqlResult result = new SparqlResult(); while (context.Input.TokenType != JsonToken.EndObject) { if (context.Input.TokenType == JsonToken.PropertyName) { //Each Property Name should be for a variable this.ParseBoundVariable(context, context.Input.Value.ToString(), result); } else { throw Error(context, "Unexpected Token '" + context.Input.TokenType.ToString() + "' encountered, expected a Property Name giving the Binding for a Variable for this Result"); } //Get Next Token if (!context.Input.Read()) { throw new RdfParseException("Unexpected End of Input while trying to parse a Binding Object"); } } //Check that all Variables are bound for a given result binding nulls where appropriate foreach (String v in context.Variables) { if (!result.HasValue(v)) { result.SetValue(v, null); } } //Add to Results if (!context.Handler.HandleResult(result)) throw ParserHelper.Stop(); } else { throw new RdfParseException("Unexpected End of Input while trying to parse a Binding Object"); } }
private void TryParseResultRow(TokenisingResultParserContext context) { IToken next = context.Tokens.Peek(); if (next.TokenType == Token.EOF) { context.Tokens.Dequeue(); return; } bool allowEOL = true, expectTab = false; int v = 0; SparqlResult result = new SparqlResult(); while (true) { next = context.Tokens.Dequeue(); switch (next.TokenType) { case Token.URI: if (expectTab) { throw ParserHelper.Error("Unexpected URI, expected a Tab between RDF Terms", next); } if (v >= context.Variables.Count) { throw ParserHelper.Error("Too many RDF Terms, only expecting " + context.Variables.Count + " terms", next); } INode uri = ParserHelper.TryResolveUri(context, next); result.SetValue(context.Variables[v], uri); v++; allowEOL = true; expectTab = true; break; case Token.BLANKNODEWITHID: if (expectTab) { throw ParserHelper.Error("Unexpected Blank Node, expected a Tab between RDF Terms", next); } if (v >= context.Variables.Count) { throw ParserHelper.Error("Too many RDF Terms, only expecting " + context.Variables.Count + " terms", next); } INode blank = context.Handler.CreateBlankNode(next.Value.Substring(2)); result.SetValue(context.Variables[v], blank); v++; allowEOL = true; expectTab = true; break; case Token.LITERAL: case Token.LONGLITERAL: case Token.PLAINLITERAL: if (expectTab) { throw ParserHelper.Error("Unexpected Blank Node, expected a Tab between RDF Terms", next); } if (v >= context.Variables.Count) { throw ParserHelper.Error("Too many RDF Terms, only expecting " + context.Variables.Count + " terms", next); } INode lit = TryParseLiteral(context, next); result.SetValue(context.Variables[v], lit); v++; allowEOL = true; expectTab = true; break; case Token.EOL: if (allowEOL) { break; } else { if (v == context.Variables.Count - 1) { // If this is the last expected term then this must be an empty term v++; break; } throw ParserHelper.Error("Unexpected End of Line, expected a RDF Term Token", next); } case Token.TAB: if (!expectTab) { // This is an empty field if (v >= context.Variables.Count) { throw ParserHelper.Error("Too many RDF Terms, only expecting " + context.Variables.Count + " terms", next); } v++; } expectTab = false; allowEOL = false; break; case Token.EOF: if (!allowEOL) { throw ParserHelper.Error("Unexpected EOF, expected another RDF Term for the Result Row", next); } break; default: throw ParserHelper.Error("Unexpected Token '" + next.GetType().ToString() + "' encountered", next); } // Stop when we've hit the End of the Line/File if (next.TokenType == Token.EOL || next.TokenType == Token.EOF) { break; } } if (v < context.Variables.Count) { throw ParserHelper.Error("Too few RDF Terms, got " + v + " but expected " + context.Variables.Count, next); } result.SetVariableOrdering(context.Variables); if (!context.Handler.HandleResult(result)) { ParserHelper.Stop(); } }
private void TryParseResultRow(TokenisingResultParserContext context) { IToken next = context.Tokens.Peek(); if (next.TokenType == Token.EOF) { context.Tokens.Dequeue(); return; } bool allowEOL = true, expectComma = false; int v = 0; SparqlResult result = new SparqlResult(); while (true) { next = context.Tokens.Dequeue(); switch (next.TokenType) { case Token.BLANKNODEWITHID: if (expectComma) { throw ParserHelper.Error("Unexpected Blank Node, expected a comma between RDF Terms", next); } if (v >= context.Variables.Count) { throw ParserHelper.Error("Too many RDF Terms, only expecting " + context.Variables.Count + " terms", next); } INode blank = context.Handler.CreateBlankNode(next.Value.Substring(2)); result.SetValue(context.Variables[v], blank); v++; allowEOL = true; expectComma = true; break; case Token.LITERAL: case Token.PLAINLITERAL: if (expectComma) { throw ParserHelper.Error("Unexpected Blank Node, expected a comma between RDF Terms", next); } if (v >= context.Variables.Count) { throw ParserHelper.Error("Too many RDF Terms, only expecting " + context.Variables.Count + " terms", next); } // Try and guess what kind of term this is String lexicalForm = next.Value; INode value; if (lexicalForm.StartsWith("http://") || lexicalForm.StartsWith("https://") || lexicalForm.StartsWith("mailto:") || lexicalForm.StartsWith("ftp://")) { try { // Guessing a URI if starts with common URI prefix value = ParserHelper.TryResolveUri(context, next); } catch { // If invalid URI fall back to treating as literal value = context.Handler.CreateLiteralNode(lexicalForm); } } else { value = context.Handler.CreateLiteralNode(lexicalForm); } result.SetValue(context.Variables[v], value); v++; allowEOL = true; expectComma = true; break; case Token.EOL: if (allowEOL) { break; } else { if (v == context.Variables.Count - 1) { // If this is the last expected term then this must be an empty term v++; break; } throw ParserHelper.Error("Unexpected End of Line, expected a RDF Term Token", next); } case Token.COMMA: if (!expectComma) { // This is an empty field if (v >= context.Variables.Count) { throw ParserHelper.Error("Too many RDF Terms, only expecting " + context.Variables.Count + " terms", next); } v++; } expectComma = false; allowEOL = false; break; case Token.EOF: if (!allowEOL) { throw ParserHelper.Error("Unexpected EOF, expected another RDF Term for the Result Row", next); } break; default: throw ParserHelper.Error("Unexpected Token '" + next.GetType().ToString() + "' encountered", next); } // Stop when we've hit the End of the Line/File if (next.TokenType == Token.EOL || next.TokenType == Token.EOF) { break; } } result.SetVariableOrdering(context.Variables); if (!context.Handler.HandleResult(result)) { ParserHelper.Stop(); } }
/// <summary> /// Parses the XML Result Set format into a set of SPARQLResult objects /// </summary> /// <param name="context">Parser Context</param> private void Parse(SparqlXmlParserContext context) { try { context.Handler.StartResults(); // Get the Document Element and check it's a Sparql element if (!context.Input.Read()) { throw new RdfParseException("Unable to Parse a SPARQL Result Set as it was not possible to read a document element from the input"); } while (context.Input.NodeType != XmlNodeType.Element) { if (!context.Input.Read()) { throw new RdfParseException("Unable to Parse a SPARQL Result Set as it was not possible to read a document element from the input"); } } if (!context.Input.Name.Equals("sparql")) { throw new RdfParseException("Unable to Parse a SPARQL Result Set from the provided XML since the Document Element is not a <sparql> element!"); } // Go through it's attributes and check the Namespace is specified bool nsfound = false; if (context.Input.HasAttributes) { for (int i = 0; i < context.Input.AttributeCount; i++) { context.Input.MoveToNextAttribute(); if (context.Input.Name.Equals("xmlns")) { if (!context.Input.Value.Equals(SparqlSpecsHelper.SparqlNamespace)) { throw new RdfParseException("Unable to Parse a SPARQL Result Set since the <sparql> element has an incorrect Namespace!"); } else { nsfound = true; } } } } if (!nsfound) { throw new RdfParseException("Unable to Parse a SPARQL Result Set since the <sparql> element fails to specify the SPARQL Namespace!"); } // Get the Variables from the Header if (!context.Input.Read()) { throw new RdfParseException("Unable to Parse a SPARQL Result Set as could not read a <head> element from the input"); } if (!context.Input.Name.Equals("head")) { throw new RdfParseException("Unable to Parse a SPARQL Result Set since the first Child Node of the <sparql> element is not the required <head> element!"); } // Only parser <variable> and <link> elements if not an empty <head /> element if (!context.Input.IsEmptyElement) { while (context.Input.Read()) { // Stop reading when we hit the </head> if (context.Input.NodeType == XmlNodeType.EndElement && context.Input.Name.Equals("head")) { break; } // Looking for <variable> elements if (context.Input.Name.Equals("variable")) { // Should only have 1 attribute if (context.Input.AttributeCount != 1) { throw new RdfParseException("Unable to Parse a SPARQL Result Set since a <variable> element has too few/many attributes, only a 'name' attribute should be present!"); } else { // Add the Variable to the list context.Input.MoveToNextAttribute(); if (!context.Handler.HandleVariable(context.Input.Value)) { ParserHelper.Stop(); } context.Variables.Add(context.Input.Value); } } else if (context.Input.Name.Equals("link")) { // Not bothered about <link> elements } else { // Some unexpected element throw new RdfParseException("Unable to Parse a SPARQL Result Set since the <head> contains an unexpected element <" + context.Input.Name + ">!"); } } } if (!context.Input.Name.Equals("head")) { throw new RdfParseException("Unable to Parse a SPARQL Result Set as reached the end of the input before the closing </head> element was found"); } // Look at the <results> or <boolean> element if (!context.Input.Read()) { throw new RdfParseException("Unable to Parse a SPARQL Result Set as could not read a <results> element from the input"); } if (context.Input.Name.Equals("results")) { // Only parser <result> elements if it's not an empty <results /> element if (!context.Input.IsEmptyElement) { while (context.Input.Read()) { // Stop reading when we hit the </results> if (context.Input.NodeType == XmlNodeType.EndElement && context.Input.Name.Equals("results")) { break; } // Must be a <result> element if (!context.Input.Name.Equals("result")) { throw new RdfParseException("Unable to Parse a SPARQL Result Set since the <results> element contains an unexpected element <" + context.Input.Name + ">!"); } // Empty Elements generate an Empty Result if (context.Input.IsEmptyElement) { if (!context.Handler.HandleResult(new SparqlResult())) { ParserHelper.Stop(); } continue; } // Get the values of each Binding String var; INode value; SparqlResult result = new SparqlResult(); while (context.Input.Read()) { // Stop reading when we hit the </binding> if (context.Input.NodeType == XmlNodeType.EndElement && context.Input.Name.Equals("result")) { break; } // Must be a <binding> element if (!context.Input.Name.Equals("binding")) { throw new RdfParseException("Unable to Parse a SPARQL Result Set since a <result> element contains an unexpected element <" + context.Input.Name + ">!"); } // Must have only 1 attribute if (context.Input.AttributeCount != 1) { throw new RdfParseException("Unable to Parse a SPARQL Result Set since a <binding> element has too few/many attributes, only a 'name' attribute should be present!"); } // Get the Variable this is a binding for and its Value context.Input.MoveToNextAttribute(); var = context.Input.Value; if (!context.Input.Read()) { throw new RdfParseException("Unable to Parse a SPARQL Result Set as reached the end of input when the contents of a <binding> element was expected"); } value = ParseValue(context); // Check that the Variable was defined in the Header if (!context.Variables.Contains(var)) { throw new RdfParseException("Unable to Parse a SPARQL Result Set since a <binding> element attempts to bind a value to the variable '" + var + "' which is not defined in the <head> by a <variable> element!"); } // Set the Variable to the Value result.SetValue(var, value); } // Check that all Variables are bound for a given result binding nulls where appropriate foreach (String v in context.Variables) { if (!result.HasValue(v)) { result.SetValue(v, null); } } if (!context.Input.Name.Equals("result")) { throw new RdfParseException("Unable to Parse a SPARQL Result Set as reached the end of the input before a closing </result> element was found"); } // Add to results set result.SetVariableOrdering(context.Variables); if (!context.Handler.HandleResult(result)) { ParserHelper.Stop(); } } } if (!context.Input.Name.Equals("results")) { throw new RdfParseException("Unable to Parse a SPARQL Result Set as reached the end of the input before the closing </results> element was found"); } } else if (context.Input.Name.Equals("boolean")) { // Can't be any <variable> elements if (context.Variables.Count > 0) { throw new RdfParseException("Unable to Parse a SPARQL Result Set since the <boolean> element is specified but the <head> contained one/more <variable> elements which is not permitted!"); } try { // Get the value of the <boolean> element as a Boolean Boolean b = Boolean.Parse(context.Input.ReadInnerXml()); context.Handler.HandleBooleanResult(b); } catch (Exception) { throw new RdfParseException("Unable to Parse a SPARQL Result Set since the <boolean> element contained a value that could not be understood as a Boolean value!"); } } else { throw new RdfParseException("Unable to Parse a SPARQL Result Set since the second Child Node of the <sparql> element is not the required <results> or <boolean> element!"); } context.Handler.EndResults(true); } catch (RdfParsingTerminatedException) { context.Handler.EndResults(true); } catch { // Some other Error context.Handler.EndResults(false); throw; } }
/// <summary> /// Parser method which parses a Bound Variable Object which occurs within a Binding Object /// </summary> /// <param name="context">Parser Context</param> /// <param name="var">Variable Name</param> /// <param name="r">Result Object that is being constructed from the Binding Object</param> /// <param name="headSeen"></param> private void ParseBoundVariable(SparqlJsonParserContext context, string var, SparqlResult r, bool headSeen) { String nodeType, nodeLang, nodeDatatype; string nodeValue = nodeType = nodeLang = nodeDatatype = null; //Can we read the start of an Object if (context.Input.Read()) { if (context.Input.TokenType == JsonToken.StartObject) { context.Input.Read(); while (context.Input.TokenType != JsonToken.EndObject) { String token = context.Input.Value.ToString().ToLower(); //Check that we get a Property Value as a String context.Input.Read(); if (!IsValidValue(context)) { throw Error(context, "Unexpected Token '" + context.Input.TokenType + "' with value '" + context.Input.Value + "' encountered, expected a Property Value describing one of the properties of an Variable Binding"); } //Extract the Information from the Object if (token.Equals("value")) { nodeValue = context.Input.Value.ToString(); } else if (token.Equals("type")) { nodeType = context.Input.Value.ToString().ToLower(); } else if (token.Equals("lang") || token.Equals("xml:lang")) { if (nodeLang == null && nodeDatatype == null) { nodeLang = context.Input.Value.ToString(); } else { throw Error(context, "Unexpected Language Property specified for an Object Node where a Language or Datatype has already been specified"); } } else if (token.Equals("datatype")) { if (nodeDatatype == null && nodeLang == null) { nodeDatatype = context.Input.Value.ToString(); } else { throw Error(context, "Unexpected Datatype Property specified for an Object Node where a Language or Datatype has already been specified"); } } else { throw Error(context, "Unexpected Property '" + token + "' specified for an Object Node, only 'value', 'type', 'lang' and 'datatype' are valid properties"); } //Get Next Token if (!context.Input.Read()) { throw new RdfParseException("Unexpected End of Input while trying to parse a Bound Variable Object"); } } //Validate the Information if (nodeType == null) { throw new RdfParseException("Cannot parse a Node from the JSON where no 'type' property was specified in the JSON Object representing the Node"); } if (nodeValue == null) { throw new RdfParseException("Cannot parse a Node from the JSON where no 'value' property was specified in the JSON Object representing the Node"); } //Turn this information into a Node INode n; if (nodeType.Equals("uri")) { n = ParserHelper.TryResolveUri(context, nodeValue); } else if (nodeType.Equals("bnode")) { if (nodeValue.StartsWith("_:")) { n = context.Handler.CreateBlankNode(nodeValue.Substring(2)); } else if (nodeValue.Contains("://")) { n = context.Handler.CreateBlankNode(nodeValue.Substring(nodeValue.IndexOf("://", StringComparison.Ordinal) + 3)); } else if (nodeValue.Contains(":")) { n = context.Handler.CreateBlankNode(nodeValue.Substring(nodeValue.LastIndexOf(':') + 1)); } else { n = context.Handler.CreateBlankNode(nodeValue); } } else if (nodeType.Equals("literal") || nodeType.Equals("typed-literal")) { if (nodeLang != null) { n = context.Handler.CreateLiteralNode(nodeValue, nodeLang); } else if (nodeDatatype != null) { Uri dtUri = ((IUriNode)ParserHelper.TryResolveUri(context, nodeDatatype)).Uri; n = context.Handler.CreateLiteralNode(nodeValue, dtUri); } else { n = context.Handler.CreateLiteralNode(nodeValue); } } else { throw new RdfParseException("Cannot parse a Node from the JSON where the 'type' property has a value of '" + nodeType + "' which is not one of the permitted values 'uri', 'bnode', 'literal' or 'typed-literal' in the JSON Object representing the Node"); } //Check that the Variable was defined in the Header if (!context.Variables.Contains(var)) { if (headSeen) { throw new RdfParseException("Unable to Parse a SPARQL Result Set since a Binding Object attempts to bind a value to the variable '" + var + "' which is not defined in the Header Object in the value for the 'vars' property!"); } context.Variables.Add(var); } //Add to the result r.SetValue(var, n); } else { throw Error(context, "Unexpected Token '" + context.Input.TokenType + "' with value '" + context.Input.Value + "' encountered, expected the start of a Bound Variable Object"); } } else { throw Error(context, "Unexpected End of Input while trying to parse a Bound Variable Object"); } }
/// <summary> /// Parses the XML Result Set format into a set of SPARQLResult objects /// </summary> /// <param name="context">Parser Context</param> private void Parse(SparqlXmlParserContext context) { try { context.Handler.StartResults(); //Get the Document Element and check it's a Sparql element if (!context.Input.Read()) throw new RdfParseException("Unable to Parse a SPARQL Result Set as it was not possible to read a document element from the input"); while (context.Input.NodeType != XmlNodeType.Element) { if (!context.Input.Read()) throw new RdfParseException("Unable to Parse a SPARQL Result Set as it was not possible to read a document element from the input"); } if (!context.Input.Name.Equals("sparql")) { throw new RdfParseException("Unable to Parse a SPARQL Result Set from the provided XML since the Document Element is not a <sparql> element!"); } //Go through it's attributes and check the Namespace is specified bool nsfound = false; if (context.Input.HasAttributes) { for (int i = 0; i < context.Input.AttributeCount; i++) { context.Input.MoveToNextAttribute(); if (context.Input.Name.Equals("xmlns")) { if (!context.Input.Value.Equals(SparqlSpecsHelper.SparqlNamespace)) { throw new RdfParseException("Unable to Parse a SPARQL Result Set since the <sparql> element has an incorrect Namespace!"); } else { nsfound = true; } } } } if (!nsfound) { throw new RdfParseException("Unable to Parse a SPARQL Result Set since the <sparql> element fails to specify the SPARQL Namespace!"); } //Get the Variables from the Header if (!context.Input.Read()) throw new RdfParseException("Unable to Parse a SPARQL Result Set as could not read a <head> element from the input"); if (!context.Input.Name.Equals("head")) { throw new RdfParseException("Unable to Parse a SPARQL Result Set since the first Child Node of the <sparql> element is not the required <head> element!"); } //Only parser <variable> and <link> elements if not an empty <head /> element if (!context.Input.IsEmptyElement) { while (context.Input.Read()) { //Stop reading when we hit the </head> if (context.Input.NodeType == XmlNodeType.EndElement && context.Input.Name.Equals("head")) break; //Looking for <variable> elements if (context.Input.Name.Equals("variable")) { //Should only have 1 attribute if (context.Input.AttributeCount != 1) { throw new RdfParseException("Unable to Parse a SPARQL Result Set since a <variable> element has too few/many attributes, only a 'name' attribute should be present!"); } else { //Add the Variable to the list context.Input.MoveToNextAttribute(); if (!context.Handler.HandleVariable(context.Input.Value)) ParserHelper.Stop(); context.Variables.Add(context.Input.Value); } } else if (context.Input.Name.Equals("link")) { //Not bothered about <link> elements } else { //Some unexpected element throw new RdfParseException("Unable to Parse a SPARQL Result Set since the <head> contains an unexpected element <" + context.Input.Name + ">!"); } } } if (!context.Input.Name.Equals("head")) { throw new RdfParseException("Unable to Parse a SPARQL Result Set as reached the end of the input before the closing </head> element was found"); } //Look at the <results> or <boolean> element if (!context.Input.Read()) throw new RdfParseException("Unable to Parse a SPARQL Result Set as could not read a <results> element from the input"); if (context.Input.Name.Equals("results")) { //Only parser <result> elements if it's not an empty <results /> element if (!context.Input.IsEmptyElement) { while (context.Input.Read()) { //Stop reading when we hit the </results> if (context.Input.NodeType == XmlNodeType.EndElement && context.Input.Name.Equals("results")) break; //Must be a <result> element if (!context.Input.Name.Equals("result")) { throw new RdfParseException("Unable to Parse a SPARQL Result Set since the <results> element contains an unexpected element <" + context.Input.Name + ">!"); } //Empty Elements generate an Empty Result if (context.Input.IsEmptyElement) { if (!context.Handler.HandleResult(new SparqlResult())) ParserHelper.Stop(); continue; } //Get the values of each Binding String var; INode value; SparqlResult result = new SparqlResult(); while (context.Input.Read()) { //Stop reading when we hit the </binding> if (context.Input.NodeType == XmlNodeType.EndElement && context.Input.Name.Equals("result")) break; //Must be a <binding> element if (!context.Input.Name.Equals("binding")) { throw new RdfParseException("Unable to Parse a SPARQL Result Set since a <result> element contains an unexpected element <" + context.Input.Name + ">!"); } //Must have only 1 attribute if (context.Input.AttributeCount != 1) { throw new RdfParseException("Unable to Parse a SPARQL Result Set since a <binding> element has too few/many attributes, only a 'name' attribute should be present!"); } //Get the Variable this is a binding for and its Value context.Input.MoveToNextAttribute(); var = context.Input.Value; if (!context.Input.Read()) throw new RdfParseException("Unable to Parse a SPARQL Result Set as reached the end of input when the contents of a <binding> element was expected"); value = this.ParseValue(context); //Check that the Variable was defined in the Header if (!context.Variables.Contains(var)) { throw new RdfParseException("Unable to Parse a SPARQL Result Set since a <binding> element attempts to bind a value to the variable '" + var + "' which is not defined in the <head> by a <variable> element!"); } //Set the Variable to the Value result.SetValue(var, value); } //Check that all Variables are bound for a given result binding nulls where appropriate foreach (String v in context.Variables) { if (!result.HasValue(v)) { result.SetValue(v, null); } } if (!context.Input.Name.Equals("result")) { throw new RdfParseException("Unable to Parse a SPARQL Result Set as reached the end of the input before a closing </result> element was found"); } //Add to results set if (!context.Handler.HandleResult(result)) ParserHelper.Stop(); } } if (!context.Input.Name.Equals("results")) { throw new RdfParseException("Unable to Parse a SPARQL Result Set as reached the end of the input before the closing </results> element was found"); } } else if (context.Input.Name.Equals("boolean")) { //Can't be any <variable> elements if (context.Variables.Count > 0) { throw new RdfParseException("Unable to Parse a SPARQL Result Set since the <boolean> element is specified but the <head> contained one/more <variable> elements which is not permitted!"); } try { //Get the value of the <boolean> element as a Boolean Boolean b = Boolean.Parse(context.Input.ReadInnerXml()); context.Handler.HandleBooleanResult(b); } catch (Exception) { throw new RdfParseException("Unable to Parse a SPARQL Result Set since the <boolean> element contained a value that could not be understood as a Boolean value!"); } } else { throw new RdfParseException("Unable to Parse a SPARQL Result Set since the second Child Node of the <sparql> element is not the required <results> or <boolean> element!"); } context.Handler.EndResults(true); } catch (RdfParsingTerminatedException) { context.Handler.EndResults(true); } catch { //Some other Error context.Handler.EndResults(false); throw; } }
/// <summary> /// Internal method which actually parses the Result Set by traversing the RDF Graph appropriately /// </summary> /// <param name="context">Parser Context</param> private void Parse(SparqlRdfParserContext context) { try { context.Handler.StartResults(); //Create relevant Nodes context.Graph.NamespaceMap.AddNamespace("rdf", new Uri(NamespaceMapper.RDF)); context.Graph.NamespaceMap.AddNamespace("rs", new Uri(SparqlSpecsHelper.SparqlRdfResultsNamespace)); IUriNode rdfType = context.Graph.CreateUriNode("rdf:type"); IUriNode resultSetClass = context.Graph.CreateUriNode("rs:ResultSet"); IUriNode resultVariable = context.Graph.CreateUriNode("rs:resultVariable"); IUriNode solution = context.Graph.CreateUriNode("rs:solution"); IUriNode binding = context.Graph.CreateUriNode("rs:binding"); IUriNode value = context.Graph.CreateUriNode("rs:value"); IUriNode variable = context.Graph.CreateUriNode("rs:variable"); IUriNode boolean = context.Graph.CreateUriNode("rs:boolean"); //Try to get a ResultSet object Triple rset = context.Graph.Triples.WithPredicateObject(rdfType, resultSetClass).FirstOrDefault(); if (rset != null) { INode rsetID = rset.Subject; //Find the Variables the Result Set contains or the Boolean Value List<Triple> temp = context.Graph.Triples.WithSubjectPredicate(rsetID, boolean).ToList(); if (temp.Count > 0) { if (temp.Count > 1) throw new RdfParseException("Result Set has more than one boolean result defined for it"); Triple booleanResult = temp.First(); INode result = booleanResult.Object; if (result.NodeType == NodeType.Literal) { ILiteralNode lit = (ILiteralNode)result; if (lit.DataType != null) { if (lit.DataType.ToString().Equals(XmlSpecsHelper.XmlSchemaDataTypeBoolean)) { bool b; if (Boolean.TryParse(lit.Value, out b)) { context.Handler.HandleBooleanResult(b); return; } else { throw new RdfParseException("Result Set has a boolean result which is a Literal typed as boolean but which does not contain a valid boolean value"); } } else { throw new RdfParseException("Result Set has a boolean result which is a Literal which is not boolean typed"); } } else { throw new RdfParseException("Result Set has a boolean result which is a Literal which is not typed as a boolean"); } } else { throw new RdfParseException("Result Set has a boolean result which is not a Literal Node"); } } else { //We're expected one/more variables temp = context.Graph.Triples.WithSubjectPredicate(rsetID, resultVariable).ToList(); if (temp.Count > 0) { foreach (Triple t in temp) { if (t.Object.NodeType == NodeType.Literal) { if (!context.Handler.HandleVariable(((ILiteralNode)t.Object).Value)) ParserHelper.Stop(); context.Variables.Add(((ILiteralNode)t.Object).Value); } else { throw new RdfParseException("Result Set has a result variable definition which is not a Literal Node"); } } } else { throw new RdfParseException("Result Set does not define any result variables or a boolean result"); } //Then we're expecting some Solutions temp = context.Graph.Triples.WithSubjectPredicate(rsetID, solution).ToList(); foreach (Triple slnTriple in temp) { //Each Solution has some Bindings INode slnID = slnTriple.Object; bool ok = false; SparqlResult r = new SparqlResult(); foreach (Triple bindingTriple in context.Graph.Triples.WithSubjectPredicate(slnID, binding)) { //Each Binding has a Variable and a Value ok = true; INode bindingID = bindingTriple.Object; String var = String.Empty; INode val = null; //Retrieve the Variable and the Bound Value foreach (Triple valueTriple in context.Graph.Triples.WithSubject(bindingID)) { if (valueTriple.Predicate.Equals(variable)) { if (!var.Equals(String.Empty)) throw new RdfParseException("Result Set contains a Binding which refers to more than one Variable"); if (valueTriple.Object.NodeType != NodeType.Literal) throw new RdfParseException("Result Set contains a Binding which refers to a Variable but not by a Literal Node as required"); var = ((ILiteralNode)valueTriple.Object).Value; } else if (valueTriple.Predicate.Equals(value)) { if (val != null) throw new RdfParseException("Result Set contains a Binding which has more than one Value"); val = valueTriple.Object; } } if (var.Equals(String.Empty) || val == null) throw new RdfParseException("Result Set contains a Binding which doesn't contain both a Variable and a Value"); //Check that the Variable was defined in the Header if (!context.Variables.Contains(var)) { throw new RdfParseException("Unable to Parse a SPARQL Result Set since a <binding> element attempts to bind a value to the variable '" + var + "' which is not defined in the <head> by a <variable> element!"); } r.SetValue(var, val); } if (!ok) throw new RdfParseException("Result Set contains a Solution which has no Bindings"); //Check that all Variables are bound for a given result binding nulls where appropriate foreach (String v in context.Variables) { if (!r.HasValue(v)) { r.SetValue(v, null); } } if (!context.Handler.HandleResult(r)) ParserHelper.Stop(); } } } else { throw new RdfParseException("No Result Set object is defined in the Graph"); } context.Handler.EndResults(true); } catch (RdfParsingTerminatedException) { context.Handler.EndResults(true); } catch { context.Handler.EndResults(false); throw; } }
/// <summary> /// Executes a SPARQL Query on the native Quad Store /// </summary> /// <param name="sparqlQuery">SPARQL Query to execute</param> /// <returns></returns> /// <remarks> /// <para> /// This method will first attempt to parse the query into a <see cref="SparqlQuery">SparqlQuery</see> object. If this succeeds then the Query Type can be used to determine how to handle the response. /// </para> /// <para> /// If the parsing fails then the query will be executed anyway using Virtuoso's SPASQL (SPARQL + SQL) syntax. Parsing can fail because Virtuoso supports various SPARQL extensions which the library does not support. These include things like aggregate functions but also SPARQL Update statements. /// </para> /// <para> /// If you use an aggregate query which has an Integer, Decimal or Double type result then you will receive a <see cref="SparqlResultSet">SparqlResultSet</see> containing a single <see cref="SparqlResult">SparqlResult</see> which has contains a binding for a variable named <strong>Result</strong> which contains a <see cref="LiteralNode">LiteralNode</see> typed to the appropriate datatype. /// </para> /// </remarks> /// <exception cref="RdfQueryException">Thrown if an error occurs in making the query</exception> public Object Query(String sparqlQuery) { Object finalResult = null; DataTable results = new DataTable(); results.Columns.CollectionChanged += new System.ComponentModel.CollectionChangeEventHandler(Columns_CollectionChanged); //See if the query can be parsed into a SparqlQuery object //It might not since the user might use Virtuoso's extensions to Sparql in their query try { //We'll set the Parser to SPARQL 1.1 mode even though Virtuoso's SPARQL implementation has //various perculiarties in their SPARQL 1.1 implementation and we'll try and //handle the potential results in the catch branch if a valid SPARQL 1.0 query //cannot be parsed //Change made in response to a bug report by Aleksandr A. Zaripov [[email protected]] SparqlQueryParser parser = new SparqlQueryParser(); parser.SyntaxMode = SparqlQuerySyntax.Sparql_1_1; SparqlQuery query = parser.ParseFromString(sparqlQuery); switch (query.QueryType) { case SparqlQueryType.Select: case SparqlQueryType.SelectAll: case SparqlQueryType.SelectAllDistinct: case SparqlQueryType.SelectAllReduced: case SparqlQueryType.SelectDistinct: case SparqlQueryType.SelectReduced: //Type the Tables columns as System.Object foreach (SparqlVariable var in query.Variables) { if (var.IsResultVariable) { results.Columns.Add(var.Name, typeof(System.Object)); } } break; } try { this.Open(false); //Make the Query against Virtuoso VirtuosoCommand cmd = this._db.CreateCommand(); cmd.CommandText = "SPARQL " + sparqlQuery; VirtuosoDataAdapter adapter = new VirtuosoDataAdapter(cmd); adapter.Fill(results); //Decide how to process the results based on the return type switch (query.QueryType) { case SparqlQueryType.Ask: //Expect a DataTable containing a single row and column which contains a boolean if (results.Rows.Count == 1 && results.Columns.Count == 1) { bool result; int r; if (Boolean.TryParse(results.Rows[0][0].ToString(), out result)) { finalResult = new SparqlResultSet(result); } else if (Int32.TryParse(results.Rows[0][0].ToString(), out r)) { if (r == 1) { finalResult = new SparqlResultSet(true); } else { finalResult = new SparqlResultSet(false); } } else { throw new RdfQueryException("Expected a Boolean as the result of an ASK query but the non-boolean value '" + results.Rows[0][0].ToString() + "' was received"); } } else { //If we get anything else then we'll return that the result was False finalResult = new SparqlResultSet(false); } break; case SparqlQueryType.Construct: case SparqlQueryType.Describe: case SparqlQueryType.DescribeAll: //Expect a DataTable containing a single row and column which contains a String //That string will be a Turtle serialization of the Graph if (results.Rows.Count == 1 && results.Columns.Count == 1) { try { //Use StringParser to parse String data = results.Rows[0][0].ToString(); TurtleParser ttlparser = new TurtleParser(); Graph g = new Graph(); StringParser.Parse(g, data, ttlparser); finalResult = g; } catch (RdfParseException parseEx) { throw new RdfQueryException("Expected a valid Turtle serialization of the Graph resulting from a CONSTRUCT/DESCRIBE query but the result failed to parse", parseEx); } } else { throw new RdfQueryException("Expected a single string value representing the serialization of the Graph resulting from a CONSTRUCT/DESCRIBE query but this was not received"); } break; case SparqlQueryType.Select: case SparqlQueryType.SelectAll: case SparqlQueryType.SelectAllDistinct: case SparqlQueryType.SelectAllReduced: case SparqlQueryType.SelectDistinct: case SparqlQueryType.SelectReduced: //Expect a DataTable containing columns for each Result Variable and a row for each solution SparqlResultSet rset = new SparqlResultSet(); rset.SetResult(true); //Get Result Variables List<SparqlVariable> resultVars = query.Variables.Where(v => v.IsResultVariable).ToList(); foreach (SparqlVariable var in resultVars) { rset.AddVariable(var.Name); } Graph temp = new Graph(); //Convert each solution into a SPARQLResult foreach (DataRow r in results.Rows) { SparqlResult result = new SparqlResult(); foreach (SparqlVariable var in resultVars) { if (r[var.Name] != null) { result.SetValue(var.Name, this.LoadNode(temp, r[var.Name])); } } rset.AddResult(result); } finalResult = rset; break; default: throw new RdfQueryException("Unable to process the Results of an Unknown query type"); } this.Close(false); } catch { this.Close(true, true); throw; } } catch (RdfParseException) { //Unable to parse a SPARQL 1.0 query //Have to attempt to detect the return type based on the DataTable that //the SPASQL (Sparql+SQL) query gives back //Make the Query against Virtuoso VirtuosoCommand cmd = this._db.CreateCommand(); cmd.CommandText = "SPARQL " /*define output:format '_JAVA_' "*/ + sparqlQuery; VirtuosoDataAdapter adapter = new VirtuosoDataAdapter(cmd); adapter.Fill(results); //Try to detect the return type based on the DataTable configuration if (results.Rows.Count == 0 && results.Columns.Count > 0) { //No Rows but some columns implies empty SELECT results SparqlResultSet rset = new SparqlResultSet(); foreach (DataColumn col in results.Columns) { rset.AddVariable(col.ColumnName); } finalResult = rset; } else if (results.Rows.Count == 1 && results.Columns.Count == 1 && !Regex.IsMatch(sparqlQuery, "SELECT", RegexOptions.IgnoreCase)) { //Added a fix here suggested by Alexander Sidorov - not entirely happy with this fix as what happens if SELECT just happens to occur in a URI/Variable Name? //Single Row and Column implies ASK/DESCRIBE/CONSTRUCT results bool result; int r; decimal rdec; double rdbl; float rflt; if (results.Rows[0][0].ToString().Equals(String.Empty)) { //Empty Results finalResult = new SparqlResultSet(); } else if (Boolean.TryParse(results.Rows[0][0].ToString(), out result)) { //Parseable Boolean so ASK Results finalResult = new SparqlResultSet(result); } else if (Int32.TryParse(results.Rows[0][0].ToString(), out r)) { //Parseable Integer so Aggregate SELECT Query Results SparqlResultSet rset = new SparqlResultSet(); rset.AddVariable("Result"); SparqlResult res = new SparqlResult(); res.SetValue("Result", new LiteralNode(null, r.ToString(), new Uri(XmlSpecsHelper.XmlSchemaDataTypeInteger))); rset.AddResult(res); finalResult = rset; } else if (Single.TryParse(results.Rows[0][0].ToString(), out rflt)) { //Parseable Single so Aggregate SELECT Query Results SparqlResultSet rset = new SparqlResultSet(); rset.AddVariable("Result"); SparqlResult res = new SparqlResult(); res.SetValue("Result", new LiteralNode(null, rflt.ToString(), new Uri(XmlSpecsHelper.XmlSchemaDataTypeFloat))); rset.AddResult(res); finalResult = rset; } else if (Double.TryParse(results.Rows[0][0].ToString(), out rdbl)) { //Parseable Double so Aggregate SELECT Query Results SparqlResultSet rset = new SparqlResultSet(); rset.AddVariable("Result"); SparqlResult res = new SparqlResult(); res.SetValue("Result", new LiteralNode(null, rdbl.ToString(), new Uri(XmlSpecsHelper.XmlSchemaDataTypeDouble))); rset.AddResult(res); finalResult = rset; } else if (Decimal.TryParse(results.Rows[0][0].ToString(), out rdec)) { //Parseable Decimal so Aggregate SELECT Query Results SparqlResultSet rset = new SparqlResultSet(); rset.AddVariable("Result"); SparqlResult res = new SparqlResult(); res.SetValue("Result", new LiteralNode(null, rdec.ToString(), new Uri(XmlSpecsHelper.XmlSchemaDataTypeDecimal))); rset.AddResult(res); finalResult = rset; } else { //String so try and parse as Turtle try { //Use StringParser to parse String data = results.Rows[0][0].ToString(); TurtleParser ttlparser = new TurtleParser(); Graph g = new Graph(); StringParser.Parse(g, data, ttlparser); finalResult = g; } catch (RdfParseException) { //If it failed to parse then it might be the result of one of the aggregate //functions that Virtuoso extends Sparql with Graph temp = new Graph(); SparqlResultSet rset = new SparqlResultSet(); rset.AddVariable(results.Columns[0].ColumnName); SparqlResult res = new SparqlResult(); res.SetValue(results.Columns[0].ColumnName, this.LoadNode(temp, results.Rows[0][0])); //Nothing was returned here previously - fix submitted by Aleksandr A. Zaripov [[email protected]] rset.AddResult(res); finalResult = rset; } } } else { //Any other number of rows/columns we have to assume that it's normal SELECT results //Changed in response to bug report by Aleksandr A. Zaripov [[email protected]] //SELECT Query Results SparqlResultSet rset = new SparqlResultSet(); rset.SetResult(true); //Get Result Variables foreach (DataColumn col in results.Columns) { rset.AddVariable(col.ColumnName); } Graph temp = new Graph(); //Convert each solution into a SPARQLResult foreach (DataRow r in results.Rows) { SparqlResult result = new SparqlResult(); foreach (String var in rset.Variables) { if (r[var] != null) { result.SetValue(var, this.LoadNode(temp, r[var])); } } rset.AddResult(result); } finalResult = rset; } } return finalResult; }