/// <summary> /// Compares two Dates for Date ordering /// </summary> /// <param name="x">Node</param> /// <param name="y">Node</param> /// <returns></returns> protected int DateCompare(INode x, INode y) { if (x == null || y == null) { throw new RdfQueryException("Cannot evaluate date equality when one or both arguments are Null"); } try { ILiteralNode a = (ILiteralNode)x; ILiteralNode b = (ILiteralNode)y; DateTimeOffset c = SparqlSpecsHelper.ToDateTimeOffset(a); DateTimeOffset d = SparqlSpecsHelper.ToDateTimeOffset(b); if (!c.Offset.Equals(d.Offset)) { throw new RdfQueryException("Cannot order Dates which are from different time zones"); } int res = c.Year.CompareTo(d.Year); if (res == 0) { res = c.Month.CompareTo(d.Month); if (res == 0) { res = c.Day.CompareTo(d.Day); } } return(res); } catch (FormatException) { throw new RdfQueryException("Cannot evaluate date equality since one of the arguments does not have a valid lexical value for a Date"); } }
/// <summary> /// Compares two Nodes for Numeric Ordering /// </summary> /// <param name="x">Node</param> /// <param name="y">Node</param> /// <param name="type">Numeric Type</param> /// <returns></returns> protected int NumericCompare(INode x, INode y, SparqlNumericType type) { if (x == null || y == null) { throw new RdfQueryException("Cannot evaluate numeric ordering when one or both arguments are Null"); } if (type == SparqlNumericType.NaN) { throw new RdfQueryException("Cannot evaluate numeric ordering when the Numeric Type is NaN"); } ILiteralNode a = (ILiteralNode)x; ILiteralNode b = (ILiteralNode)y; switch (type) { case SparqlNumericType.Decimal: return(SparqlSpecsHelper.ToDecimal(a).CompareTo(SparqlSpecsHelper.ToDecimal(b))); case SparqlNumericType.Double: return(SparqlSpecsHelper.ToDouble(a).CompareTo(SparqlSpecsHelper.ToDouble(b))); case SparqlNumericType.Float: return(SparqlSpecsHelper.ToFloat(a).CompareTo(SparqlSpecsHelper.ToFloat(b))); case SparqlNumericType.Integer: return(SparqlSpecsHelper.ToInteger(a).CompareTo(SparqlSpecsHelper.ToInteger(b))); default: throw new RdfQueryException("Cannot evaluate numeric equality since of the arguments is not numeric"); } }
/// <summary> /// Evaluates the expression /// </summary> /// <param name="context">Evaluation Context</param> /// <param name="bindingID">Binding ID</param> /// <returns></returns> public override IValuedNode Evaluate(SparqlEvaluationContext context, int bindingID) { IValuedNode x = this._leftExpr.Evaluate(context, bindingID); IValuedNode y = this._rightExpr.Evaluate(context, bindingID); return(new BooleanNode(null, SparqlSpecsHelper.Equality(x, y))); }
/// <summary> /// Computes the Effective Boolean Value of this Expression as evaluated for a given Binding /// </summary> /// <param name="context">Evaluation Context</param> /// <param name="bindingID">Binding ID</param> /// <returns></returns> public override bool EffectiveBooleanValue(SparqlEvaluationContext context, int bindingID) { INode x = this._leftExpr.Value(context, bindingID); INode y = this._rightExpr.Value(context, bindingID); return(SparqlSpecsHelper.Inequality(x, y)); }
public void SparqlDateTimeEquality(String x, String y, bool equals) { IGraph g = new Graph(); INode dateTime1 = g.CreateLiteralNode(x, UriFactory.Create(XmlSpecsHelper.XmlSchemaDataTypeDateTime)); INode dateTime2 = g.CreateLiteralNode(y, UriFactory.Create(XmlSpecsHelper.XmlSchemaDataTypeDateTime)); if (equals) { Assert.IsTrue(SparqlSpecsHelper.DateTimeEquality(dateTime1, dateTime2)); Assert.IsTrue(SparqlSpecsHelper.DateTimeEquality(dateTime2, dateTime1)); Assert.IsTrue(SparqlSpecsHelper.Equality(dateTime1, dateTime2)); Assert.IsTrue(SparqlSpecsHelper.Equality(dateTime2, dateTime1)); Assert.IsFalse(SparqlSpecsHelper.Inequality(dateTime1, dateTime2)); Assert.IsFalse(SparqlSpecsHelper.Inequality(dateTime2, dateTime1)); } else { Assert.IsFalse(SparqlSpecsHelper.DateTimeEquality(dateTime1, dateTime2)); Assert.IsFalse(SparqlSpecsHelper.DateTimeEquality(dateTime2, dateTime1)); Assert.IsFalse(SparqlSpecsHelper.Equality(dateTime1, dateTime2)); Assert.IsFalse(SparqlSpecsHelper.Equality(dateTime2, dateTime1)); Assert.IsTrue(SparqlSpecsHelper.Inequality(dateTime1, dateTime2)); Assert.IsTrue(SparqlSpecsHelper.Inequality(dateTime2, dateTime1)); } }
/// <summary> /// Gets the Effective Boolean Value of this Expression as evaluated for a given Binding /// </summary> /// <param name="context">Evaluation Context</param> /// <param name="bindingID">Binding ID</param> /// <returns></returns> public virtual bool EffectiveBooleanValue(SparqlEvaluationContext context, int bindingID) { try { switch (this.NumericType(context, bindingID)) { case SparqlNumericType.Double: double dblvalue = this.DoubleValue(context, bindingID); return(!(dblvalue == 0.0d)); case SparqlNumericType.Float: float fvalue = this.FloatValue(context, bindingID); return(!(fvalue == 0.0f)); case SparqlNumericType.Decimal: decimal decvalue = this.DecimalValue(context, bindingID); return(!(decvalue == 0)); case SparqlNumericType.Integer: long intvalue = this.IntegerValue(context, bindingID); return(!(intvalue == 0)); default: return(false); } } catch (RdfQueryException) { //return false; return(SparqlSpecsHelper.EffectiveBooleanValue(this.Value(context, bindingID))); } }
public void SparqlDateTimeMixedIncomparable(String x, String y) { IGraph g = new Graph(); INode dateTime1 = g.CreateLiteralNode(x, UriFactory.Create(XmlSpecsHelper.XmlSchemaDataTypeDateTime)); INode date2 = g.CreateLiteralNode(y, UriFactory.Create(XmlSpecsHelper.XmlSchemaDataTypeDate)); SparqlSpecsHelper.DateTimeEquality(dateTime1, date2); }
public static bool IsHexEncoding(String value, int index) { if (index + 2 >= value.Length) { return(false); } return(value[0] == '%' && SparqlSpecsHelper.IsHex(value[1]) && SparqlSpecsHelper.IsHex(value[2])); }
/// <summary> /// Return true if the character sequence starting at the specifie offset is a URI hex-encoded character /// </summary> /// <param name="str">The input string</param> /// <param name="index">The character offset from which to start the check for a hex-encoded character</param> /// <returns></returns> public static bool IsHexEncoding(this String str, int index) { if (index + 2 >= str.Length) { return(false); } return(str[0] == '%' && SparqlSpecsHelper.IsHex(str[1]) && SparqlSpecsHelper.IsHex(str[2])); }
public void SparqlDateTimeMixedIncomparable(String x, String y) { IGraph g = new Graph(); INode dateTime1 = g.CreateLiteralNode(x, UriFactory.Create(XmlSpecsHelper.XmlSchemaDataTypeDateTime)); INode date2 = g.CreateLiteralNode(y, UriFactory.Create(XmlSpecsHelper.XmlSchemaDataTypeDate)); Assert.Throws <RdfQueryException>(() => SparqlSpecsHelper.DateTimeEquality(dateTime1, date2)); }
/// <summary> /// Computes the Numeric Value of this Expression as evaluated for a given Binding (if it has a numeric value) /// </summary> /// <param name="context">Evaluation Context</param> /// <param name="bindingID">Binding ID</param> /// <returns></returns> public Object NumericValue(SparqlEvaluationContext context, int bindingID) { INode value = this.Value(context, bindingID); if (value != null) { if (value.NodeType == NodeType.Literal) { ILiteralNode lit = (ILiteralNode)value; if (!lit.Language.Equals(String.Empty)) { //If there's a Language Tag implied type is string so no numeric value throw new RdfQueryException("Cannot calculate the Numeric Value of literal with a language specifier"); } else if (lit.DataType == null) { throw new RdfQueryException("Cannot calculate the Numeric Value of an untyped Literal"); } else { try { switch (SparqlSpecsHelper.GetNumericTypeFromDataTypeUri(lit.DataType)) { case SparqlNumericType.Decimal: return(Decimal.Parse(lit.Value)); case SparqlNumericType.Double: return(Double.Parse(lit.Value)); case SparqlNumericType.Float: return(Single.Parse(lit.Value)); case SparqlNumericType.Integer: return(Int64.Parse(lit.Value)); case SparqlNumericType.NaN: default: throw new RdfQueryException("Cannot calculate the Numeric Value of a literal since its Data Type URI does not correspond to a Data Type URI recognised as a Numeric Type in the SPARQL Specification"); } } catch (FormatException fEx) { throw new RdfQueryException("Cannot calculate the Numeric Value of a Literal since the Value contained is not a valid value in it's given Data Type", fEx); } } } else { throw new RdfQueryException("Cannot calculate the Numeric Value of a non-literal RDF Term"); } } else { throw new RdfQueryException("Cannot calculate the Numeric Value of an unbound Variable"); } }
private void TestQNameUnescaping(String input, String expected) { Console.WriteLine("Input = " + input); Assert.False(SparqlSpecsHelper.IsValidQName(input, SparqlQuerySyntax.Sparql_1_0), "Expected QName to be invalid in SPARQL 1.0 syntax"); Assert.True(SparqlSpecsHelper.IsValidQName(input, SparqlQuerySyntax.Sparql_1_1), "Expected a Valid QName as test input"); Console.WriteLine("Output = " + SparqlSpecsHelper.UnescapeQName(input)); Console.WriteLine("Expected = " + expected); Assert.Equal(expected, SparqlSpecsHelper.UnescapeQName(input)); }
/// <summary> /// Creates a new Node Expression /// </summary> /// <param name="n">Node</param> public NodeExpressionTerm(INode n) { this._node = n; //Compute the EBV try { this._ebv = SparqlSpecsHelper.EffectiveBooleanValue(this._node); } catch { this._ebv = false; } }
/// <summary> /// Is something a valid partial variable name? /// </summary> /// <param name="value">Value</param> /// <returns></returns> protected virtual bool IsValidPartialVariableName(String value) { if (value.Length == 0) { return(false); } if (value[0] != '$' && value[0] != '?') { return(false); } if (value.Length == 1) { return(true); } char[] cs = value.ToCharArray(1, value.Length - 1); //First Character must be from PN_CHARS_U or a digit char first = cs[0]; if (Char.IsDigit(first) || SparqlSpecsHelper.IsPNCharsU(first)) { if (cs.Length > 1) { for (int i = 1; i < cs.Length; i++) { //Middle Chars must be from PN_CHARS or a '.' if (!(cs[i] == '.' || SparqlSpecsHelper.IsPNChars(cs[i]))) { return(false); } //Can't do the last character specific test because this is only a partial test } return(true); } else { return(true); } } else { return(false); } }
/// <summary> /// Evaluates the expression. /// </summary> /// <param name="context">Evaluation Context.</param> /// <param name="bindingID">Binding ID.</param> /// <returns></returns> public override IValuedNode Evaluate(SparqlEvaluationContext context, int bindingID) { INode result = _expr.Evaluate(context, bindingID); if (result != null) { if (_expressions.Count == 0) { return(new BooleanNode(null, true)); } // Have to use SPARQL Value Equality here // If any expressions error and nothing in the set matches then an error is thrown bool errors = false; foreach (ISparqlExpression expr in _expressions) { try { INode temp = expr.Evaluate(context, bindingID); if (SparqlSpecsHelper.Equality(result, temp)) { return(new BooleanNode(null, false)); } } catch { errors = true; } } if (errors) { throw new RdfQueryException("One/more expressions in a Set function failed to evaluate"); } else { return(new BooleanNode(null, true)); } } else { return(new BooleanNode(null, true)); } }
/// <summary> /// Gets the boolean value. /// </summary> /// <returns></returns> public bool AsBoolean() { switch (_numType) { case SparqlNumericType.Integer: return(AsInteger() != 0); case SparqlNumericType.Decimal: return(AsDecimal() != Decimal.Zero); case SparqlNumericType.Float: return(AsFloat() != 0.0f && !float.IsNaN(AsFloat())); case SparqlNumericType.Double: return(AsDouble() != 0.0d && !double.IsNaN(AsDouble())); default: return(SparqlSpecsHelper.EffectiveBooleanValue(this)); } }
private IToken TryGetVariable() { // Consume first Character which must be a ?/$ ConsumeCharacter(); // Consume other valid Characters char next = Peek(); while (Char.IsLetterOrDigit(next) || UnicodeSpecsHelper.IsLetterOrDigit(next) || next == '-' || next == '_' || next == '\\') { if (next == '\\') { // Check its a valid Escape HandleEscapes(TokeniserEscapeMode.QName); } else { ConsumeCharacter(); } next = Peek(); } // Validate String value = Value; if (value.EndsWith(".")) { Backtrack(); value = value.Substring(0, value.Length - 1); } if (SparqlSpecsHelper.IsValidVarName(value)) { return(new VariableToken(value, CurrentLine, StartPosition, EndPosition)); } else { throw Error("The value '" + value + "' is not valid a Variable Name"); } }
/// <summary> /// Formats a SPARQL Aggregate /// </summary> /// <param name="agg">SPARQL Aggregate</param> /// <returns></returns> protected virtual String FormatAggregate(ISparqlAggregate agg) { StringBuilder output = new StringBuilder(); if (SparqlSpecsHelper.IsAggregateFunctionKeyword(agg.Functor)) { output.Append(agg.Functor); } else { String aggQName; if (this._qnameMapper.ReduceToQName(agg.Functor, out aggQName)) { output.Append(aggQName); } else { output.Append('<'); output.Append(this.FormatUri(agg.Functor)); output.Append('>'); } } output.Append('('); List <ISparqlExpression> args = agg.Arguments.ToList(); for (int i = 0; i < args.Count; i++) { output.Append(this.FormatExpression(args[i])); if (i < args.Count - 1 && !(args[i] is DistinctModifier)) { output.Append(", "); } } output.Append(')'); return(output.ToString()); }
/// <summary> /// Gets the boolean value of the string /// </summary> /// <returns></returns> public bool AsBoolean() { return(SparqlSpecsHelper.EffectiveBooleanValue(this)); }
/// <summary> /// Determines whether a QName is valid /// </summary> /// <param name="value">Value</param> /// <returns></returns> protected override bool IsValidQName(string value) { return(SparqlSpecsHelper.IsValidQName(value, SparqlQuerySyntax.Sparql_1_0)); }
/// <summary> /// Formats a SPARQL Expression /// </summary> /// <param name="expr">SPARQL Expression</param> /// <returns></returns> protected virtual String FormatExpression(ISparqlExpression expr) { StringBuilder output = new StringBuilder(); try { switch (expr.Type) { case SparqlExpressionType.Aggregate: if (expr is AggregateTerm) { AggregateTerm agg = (AggregateTerm)expr; output.Append(this.FormatAggregate(agg.Aggregate)); } else { output.Append(expr.ToString()); } break; case SparqlExpressionType.BinaryOperator: ISparqlExpression lhs = expr.Arguments.First(); ISparqlExpression rhs = expr.Arguments.Skip(1).First(); //Format the Expression wrapping the LHS and/or RHS in brackets if required //to ensure that ordering of operators is preserved if (lhs.Type == SparqlExpressionType.BinaryOperator) { output.Append('('); output.Append(this.FormatExpression(lhs)); output.Append(')'); } else { output.Append(this.FormatExpression(lhs)); } output.Append(' '); output.Append(expr.Functor); output.Append(' '); if (rhs.Type == SparqlExpressionType.BinaryOperator) { output.Append('('); output.Append(this.FormatExpression(rhs)); output.Append(')'); } else { output.Append(this.FormatExpression(rhs)); } break; case SparqlExpressionType.Function: //Show either a Keyword/URI/QName as appropriate if (SparqlSpecsHelper.IsFunctionKeyword(expr.Functor)) { output.Append(expr.Functor); } else { String funcQname; if (this._qnameMapper.ReduceToQName(expr.Functor, out funcQname)) { output.Append(funcQname); } else { output.Append('<'); output.Append(this.FormatUri(expr.Functor)); output.Append('>'); } } //Add Arguments list output.Append('('); List <ISparqlExpression> args = expr.Arguments.ToList(); for (int i = 0; i < args.Count; i++) { output.Append(this.FormatExpression(args[i])); if (i < args.Count - 1) { output.Append(", "); } } output.Append(')'); break; case SparqlExpressionType.GraphOperator: output.Append(expr.Functor); output.Append(' '); List <ISparqlExpression> gArgs = expr.Arguments.ToList(); if (gArgs.Count > 1) { throw new RdfOutputException("Error Formatting SPARQL Expression - Expressions of type GraphOperator are only allowed a single argument"); } for (int i = 0; i < gArgs.Count; i++) { output.Append(this.FormatExpression(gArgs[i])); if (i < gArgs.Count - 1) { output.Append(", "); } } break; case SparqlExpressionType.Primary: //If Node/Numeric Term then use Node Formatting otherwise use ToString() on the expression if (expr is ConstantTerm) { ConstantTerm nodeTerm = (ConstantTerm)expr; output.Append(this.Format(nodeTerm.Evaluate(null, 0))); } else if (expr is GraphPatternTerm) { GraphPatternTerm gp = (GraphPatternTerm)expr; output.Append(this.Format(gp.Pattern)); } else { output.Append(expr.ToString()); } break; case SparqlExpressionType.SetOperator: //Add First Argument and Set Operator output.Append(this.FormatExpression(expr.Arguments.First())); output.Append(' '); output.Append(expr.Functor); //Add Set output.Append(" ("); List <ISparqlExpression> set = expr.Arguments.Skip(1).ToList(); for (int i = 0; i < set.Count; i++) { output.Append(this.FormatExpression(set[i])); if (i < set.Count - 1) { output.Append(", "); } } output.Append(')'); break; case SparqlExpressionType.UnaryOperator: //Just Functor then Expression output.Append(expr.Functor); output.Append(this.FormatExpression(expr.Arguments.First())); break; } } catch (RdfOutputException) { throw; } catch (Exception ex) { throw new RdfOutputException("Error formatting a SPARQL Expression - the Expression may have the wrong number of arguments for the reported expression type", ex); } return(output.ToString()); }
private IToken TryGetNumericLiteral() { bool dotoccurred = false; bool expoccurred = false; bool negoccurred = false; if (Length == 1) { dotoccurred = true; } char next = Peek(); while (Char.IsDigit(next) || next == '-' || next == '+' || next == 'e' || (next == '.' && !dotoccurred)) { // Consume the Character ConsumeCharacter(); if (next == '+') { // Can only be first character in the numeric literal or come immediately after the 'e' if (Length > 1 && !Value.EndsWith("e+")) { throw Error("Unexpected Character (Code " + (int)next + ") +\nThe plus sign can only occur once at the Start of a Numeric Literal and once immediately after the 'e' exponent specifier, if this was intended as an additive operator please insert space to disambiguate this"); } } if (next == '-') { if (negoccurred && !Value.EndsWith("e-")) { // Negative sign already seen throw Error("Unexpected Character (Code " + (int)next + ") -\nThe minus sign can only occur once at the Start of a Numeric Literal, if this was intended as a subtractive operator please insert space to disambiguate this"); } else { negoccurred = true; // Check this is at the start of the string or immediately after the 'e' if (Length > 1 && !Value.EndsWith("e-")) { throw Error("Unexpected Character (Code " + (int)next + ") -\nThe minus sign can only occur at the Start of a Numeric Literal and once immediately after the 'e' exponent specifier, if this was intended as a subtractive operator please insert space to disambiguate this"); } } } else if (next == 'e') { if (expoccurred) { // Exponent already seen throw Error("Unexpected Character (Code " + (int)next + " e\nThe Exponent specifier can only occur once in a Numeric Literal"); } else { expoccurred = true; // Check that it isn't the start of the string if (Length == 1) { throw Error("Unexpected Character (Code " + (int)next + " e\nThe Exponent specifier cannot occur at the start of a Numeric Literal"); } } } else if (next == '.') { dotoccurred = true; } next = Peek(); } // Decimals can't end with a . so backtrack if (Value.EndsWith(".")) { Backtrack(); } String value = Value; if (!SparqlSpecsHelper.IsValidNumericLiteral(value)) { // Invalid Numeric Literal throw Error("The format of the Numeric Literal '" + Value + "' is not valid!"); } // Return the Token LastTokenType = Token.PLAINLITERAL; return(new PlainLiteralToken(Value, CurrentLine, StartPosition, EndPosition)); }
/// <summary> /// Performs a SPARQL Query against the underlying Store /// </summary> /// <param name="rdfHandler">RDF Handler</param> /// <param name="resultsHandler">SPARQL Results Handler</param> /// <param name="sparqlQuery">SPARQL Query</param> /// <returns></returns> public void Query(IRdfHandler rdfHandler, ISparqlResultsHandler resultsHandler, string sparqlQuery) { try { //First off parse the Query to see what kind of query it is SparqlQuery q; try { q = this._parser.ParseFromString(sparqlQuery); } catch (RdfParseException parseEx) { throw; } catch (Exception ex) { throw new RdfStorageException("An unexpected error occurred while trying to parse the SPARQL Query prior to sending it to the Store, see inner exception for details", ex); } //Now select the Accept Header based on the query type String accept = (SparqlSpecsHelper.IsSelectQuery(q.QueryType) || q.QueryType == SparqlQueryType.Ask) ? MimeTypesHelper.HttpSparqlAcceptHeader : MimeTypesHelper.HttpAcceptHeader; //Create the Request HttpWebRequest request; Dictionary <String, String> queryParams = new Dictionary <string, string>(); if (sparqlQuery.Length < 2048) { queryParams.Add("query", sparqlQuery); request = this.CreateRequest("/sparql", accept, "GET", queryParams); } else { request = this.CreateRequest("/sparql", accept, "POST", queryParams); //Build the Post Data and add to the Request Body request.ContentType = MimeTypesHelper.WWWFormURLEncoded; StringBuilder postData = new StringBuilder(); postData.Append("query="); postData.Append(HttpUtility.UrlEncode(sparqlQuery)); StreamWriter writer = new StreamWriter(request.GetRequestStream()); writer.Write(postData); writer.Close(); } #if DEBUG if (Options.HttpDebugging) { Tools.HttpDebugRequest(request); } #endif //Get the Response and process based on the Content Type using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) { #if DEBUG if (Options.HttpDebugging) { Tools.HttpDebugResponse(response); } #endif StreamReader data = new StreamReader(response.GetResponseStream()); String ctype = response.ContentType; if (SparqlSpecsHelper.IsSelectQuery(q.QueryType) || q.QueryType == SparqlQueryType.Ask) { //ASK/SELECT should return SPARQL Results ISparqlResultsReader resreader = MimeTypesHelper.GetSparqlParser(ctype, q.QueryType == SparqlQueryType.Ask); resreader.Load(resultsHandler, data); response.Close(); } else { //CONSTRUCT/DESCRIBE should return a Graph IRdfReader rdfreader = MimeTypesHelper.GetParser(ctype); rdfreader.Load(rdfHandler, data); response.Close(); } } } catch (WebException webEx) { if (webEx.Response != null) { #if DEBUG if (Options.HttpDebugging) { Tools.HttpDebugResponse((HttpWebResponse)webEx.Response); } #endif if (webEx.Response.ContentLength > 0) { try { String responseText = new StreamReader(webEx.Response.GetResponseStream()).ReadToEnd(); throw new RdfQueryException("A HTTP error occured while querying the Store. Store returned the following error message: " + responseText, webEx); } catch { throw new RdfQueryException("A HTTP error occurred while querying the Store", webEx); } } else { throw new RdfQueryException("A HTTP error occurred while querying the Store", webEx); } } else { throw new RdfQueryException("A HTTP error occurred while querying the Store", webEx); } } }
/// <summary> /// Casts the value of the inner Expression to a Boolean. /// </summary> /// <param name="context">Evaluation Context.</param> /// <param name="bindingID">Binding ID.</param> /// <returns></returns> public override IValuedNode Evaluate(SparqlEvaluationContext context, int bindingID) { IValuedNode n = _expr.Evaluate(context, bindingID);//.CoerceToBoolean(); // if (n == null) // { // throw new RdfQueryException("Cannot cast a Null to a xsd:boolean"); // } ////New method should be much faster // if (n is BooleanNode) return n; // return new BooleanNode(null, n.AsBoolean()); switch (n.NodeType) { case NodeType.Blank: case NodeType.GraphLiteral: case NodeType.Uri: throw new RdfQueryException("Cannot cast a Blank/URI/Graph Literal Node to a xsd:boolean"); case NodeType.Literal: // See if the value can be cast if (n is BooleanNode) { return(n); } ILiteralNode lit = (ILiteralNode)n; if (lit.DataType != null) { string dt = lit.DataType.ToString(); if (dt.Equals(XmlSpecsHelper.XmlSchemaDataTypeBoolean)) { // Already a Boolean bool b; if (Boolean.TryParse(lit.Value, out b)) { return(new BooleanNode(lit.Graph, b)); } else { throw new RdfQueryException("Invalid Lexical Form for xsd:boolean"); } } // Cast based on Numeric Type SparqlNumericType type = SparqlSpecsHelper.GetNumericTypeFromDataTypeUri(dt); switch (type) { case SparqlNumericType.Decimal: Decimal dec; if (Decimal.TryParse(lit.Value, NumberStyles.Any, CultureInfo.InvariantCulture, out dec)) { if (dec.Equals(Decimal.Zero)) { return(new BooleanNode(lit.Graph, false)); } else { return(new BooleanNode(lit.Graph, true)); } } else { throw new RdfQueryException("Cannot cast the value '" + lit.Value + "' to a xsd:decimal as an intermediate stage in casting to a xsd:boolean"); } case SparqlNumericType.Double: Double dbl; if (Double.TryParse(lit.Value, NumberStyles.Any, CultureInfo.InvariantCulture, out dbl)) { if (Double.IsNaN(dbl) || dbl == 0.0d) { return(new BooleanNode(lit.Graph, false)); } else { return(new BooleanNode(lit.Graph, true)); } } else { throw new RdfQueryException("Cannot cast the value '" + lit.Value + "' to a xsd:double as an intermediate stage in casting to a xsd:boolean"); } case SparqlNumericType.Integer: Int64 i; if (Int64.TryParse(lit.Value, out i)) { if (i == 0) { return(new BooleanNode(lit.Graph, false)); } else { return(new BooleanNode(lit.Graph, true)); } } else { throw new RdfQueryException("Cannot cast the value '" + lit.Value + "' to a xsd:integer as an intermediate stage in casting to a xsd:boolean"); } case SparqlNumericType.NaN: if (dt.Equals(XmlSpecsHelper.XmlSchemaDataTypeDateTime)) { // DateTime cast forbidden throw new RdfQueryException("Cannot cast a xsd:dateTime to a xsd:boolean"); } else { Boolean b; if (Boolean.TryParse(lit.Value, out b)) { return(new BooleanNode(lit.Graph, b)); } else { throw new RdfQueryException("Cannot cast the value '" + lit.Value + "' to a xsd:boolean"); } } default: throw new RdfQueryException("Cannot cast the value '" + lit.Value + "' to a xsd:boolean"); } } else { Boolean b; if (Boolean.TryParse(lit.Value, out b)) { return(new BooleanNode(lit.Graph, b)); } else { throw new RdfQueryException("Cannot cast the value '" + lit.Value + "' to a xsd:boolean"); } } default: throw new RdfQueryException("Cannot cast an Unknown Node to a xsd:decimal"); } }
/// <summary> /// Computes the Effective Boolean Value of this Expression as evaluated for a given Binding /// </summary> /// <param name="context">Evaluation Context</param> /// <param name="bindingID">Binding ID</param> /// <returns></returns> public bool EffectiveBooleanValue(SparqlEvaluationContext context, int bindingID) { INode value = this.Value(context, bindingID); return(SparqlSpecsHelper.EffectiveBooleanValue(value)); }
/// <summary> /// Determines the Effective Boolean Value of the expression for the given Binding in the given Context /// </summary> /// <param name="context">Evaluation Context</param> /// <param name="bindingID">Binding ID</param> /// <returns></returns> public override bool EffectiveBooleanValue(SparqlEvaluationContext context, int bindingID) { try { //While we could use NumericType or NumericValue for Numeric Expressions we can't guarantee that //this would work properly INode temp = this._expr.Value(context, bindingID); if (temp.NodeType == NodeType.Literal) { ILiteralNode lit = (ILiteralNode)temp; //No DatatType means not numeric if (lit.DataType == null) { return(false); } //Get the Numeric Type from the DataType URI SparqlNumericType type = SparqlSpecsHelper.GetNumericTypeFromDataTypeUri(lit.DataType); //Now check the lexical value switch (type) { case SparqlNumericType.Decimal: //Decimal - just regex on lexical form return(SparqlSpecsHelper.IsDecimal(lit.Value)); case SparqlNumericType.Double: case SparqlNumericType.Float: //Double/Float just regex on lexical form return(SparqlSpecsHelper.IsDouble(lit.Value)); case SparqlNumericType.Integer: //Integer Type so could be any of the supported types switch (lit.DataType.ToString()) { case XmlSpecsHelper.XmlSchemaDataTypeByte: //Byte - have to try parsing it SByte sb; return(SByte.TryParse(lit.Value, out sb)); case XmlSpecsHelper.XmlSchemaDataTypeUnsignedByte: //Unsigned Byte - have to try parsing it Byte b; return(Byte.TryParse(lit.Value, out b) && b >= 0); case XmlSpecsHelper.XmlSchemaDataTypeInt: case XmlSpecsHelper.XmlSchemaDataTypeInteger: case XmlSpecsHelper.XmlSchemaDataTypeLong: case XmlSpecsHelper.XmlSchemaDataTypeShort: //Standard Integer - can just regex on its lexical form return(SparqlSpecsHelper.IsInteger(lit.Value)); case XmlSpecsHelper.XmlSchemaDataTypeNegativeInteger: case XmlSpecsHelper.XmlSchemaDataTypeNonPositiveInteger: //Negative Integer - can just regex on its lexical form //plus ensure that the value starts with a - return(lit.Value.StartsWith("-") && SparqlSpecsHelper.IsInteger(lit.Value)); case XmlSpecsHelper.XmlSchemaDataTypeNonNegativeInteger: case XmlSpecsHelper.XmlSchemaDataTypePositiveInteger: case XmlSpecsHelper.XmlSchemaDataTypeUnsignedInt: case XmlSpecsHelper.XmlSchemaDataTypeUnsignedLong: case XmlSpecsHelper.XmlSchemaDataTypeUnsignedShort: //Positive Integer - can just regex on its lexical form //plus ensure that the value doesn't start with a - return(!lit.Value.StartsWith("-") && SparqlSpecsHelper.IsInteger(lit.Value)); default: //Otherwise not numeric return(false); } default: return(false); } } else { return(false); } } catch (RdfQueryException) { return(false); } }
/// <summary> /// Queries the store asynchronously /// </summary> /// <param name="sparqlQuery">SPARQL Query</param> /// <param name="rdfHandler">RDF Handler</param> /// <param name="resultsHandler">Results Handler</param> /// <param name="callback">Callback</param> /// <param name="state">State to pass to the callback</param> public void Query(IRdfHandler rdfHandler, ISparqlResultsHandler resultsHandler, string sparqlQuery, AsyncStorageCallback callback, object state) { try { // First off parse the Query to see what kind of query it is SparqlQuery q; try { q = _parser.ParseFromString(sparqlQuery); } catch (RdfParseException parseEx) { callback(this, new AsyncStorageCallbackArgs(AsyncStorageOperation.SparqlQueryWithHandler, parseEx), state); return; } catch (Exception ex) { callback(this, new AsyncStorageCallbackArgs(AsyncStorageOperation.SparqlQueryWithHandler, new RdfStorageException("An unexpected error occurred while trying to parse the SPARQL Query prior to sending it to the Store, see inner exception for details", ex)), state); return; } // Now select the Accept Header based on the query type String accept = (SparqlSpecsHelper.IsSelectQuery(q.QueryType) || q.QueryType == SparqlQueryType.Ask) ? MimeTypesHelper.HttpSparqlAcceptHeader : MimeTypesHelper.HttpAcceptHeader; // Create the Request, for simplicity async requests are always POST HttpWebRequest request = (HttpWebRequest)WebRequest.Create(_endpoint.Uri); request.Accept = accept; request.Method = "POST"; request.ContentType = MimeTypesHelper.Utf8WWWFormURLEncoded; request = ApplyRequestOptions(request); Tools.HttpDebugRequest(request); request.BeginGetRequestStream(r => { try { Stream stream = request.EndGetRequestStream(r); using (StreamWriter writer = new StreamWriter(stream, new UTF8Encoding(Options.UseBomForUtf8))) { writer.Write("query="); writer.Write(HttpUtility.UrlEncode(sparqlQuery)); writer.Close(); } request.BeginGetResponse(r2 => { // Get the Response and process based on the Content Type try { HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(r2); Tools.HttpDebugResponse(response); StreamReader data = new StreamReader(response.GetResponseStream()); String ctype = response.ContentType; if (SparqlSpecsHelper.IsSelectQuery(q.QueryType) || q.QueryType == SparqlQueryType.Ask) { // ASK/SELECT should return SPARQL Results ISparqlResultsReader resreader = MimeTypesHelper.GetSparqlParser(ctype, q.QueryType == SparqlQueryType.Ask); resreader.Load(resultsHandler, data); response.Close(); } else { // CONSTRUCT/DESCRIBE should return a Graph IRdfReader rdfreader = MimeTypesHelper.GetParser(ctype); rdfreader.Load(rdfHandler, data); response.Close(); } callback(this, new AsyncStorageCallbackArgs(AsyncStorageOperation.SparqlQueryWithHandler, sparqlQuery, rdfHandler, resultsHandler), state); } catch (WebException webEx) { callback(this, new AsyncStorageCallbackArgs(AsyncStorageOperation.SparqlQueryWithHandler, StorageHelper.HandleHttpQueryError(webEx)), state); } catch (Exception ex) { callback(this, new AsyncStorageCallbackArgs(AsyncStorageOperation.SparqlQueryWithHandler, StorageHelper.HandleQueryError(ex)), state); } }, state); } catch (WebException webEx) { callback(this, new AsyncStorageCallbackArgs(AsyncStorageOperation.SparqlQueryWithHandler, StorageHelper.HandleHttpQueryError(webEx)), state); } catch (Exception ex) { callback(this, new AsyncStorageCallbackArgs(AsyncStorageOperation.SparqlQueryWithHandler, StorageHelper.HandleQueryError(ex)), state); } }, state); } catch (WebException webEx) { callback(this, new AsyncStorageCallbackArgs(AsyncStorageOperation.SparqlQueryWithHandler, StorageHelper.HandleHttpQueryError(webEx)), state); } catch (Exception ex) { callback(this, new AsyncStorageCallbackArgs(AsyncStorageOperation.SparqlQueryWithHandler, StorageHelper.HandleQueryError(ex)), state); } }
/// <summary> /// Processes a SPARQL Query sending the results to a RDF/SPARQL Results handler as appropriate /// </summary> /// <param name="rdfHandler">RDF Handler</param> /// <param name="resultsHandler">Results Handler</param> /// <param name="query">SPARQL Query</param> public void ProcessQuery(IRdfHandler rdfHandler, ISparqlResultsHandler resultsHandler, SparqlQuery query) { //Do Handler null checks before evaluating the query if (query == null) { throw new ArgumentNullException("query", "Cannot evaluate a null query"); } if (rdfHandler == null && (query.QueryType == SparqlQueryType.Construct || query.QueryType == SparqlQueryType.Describe || query.QueryType == SparqlQueryType.DescribeAll)) { throw new ArgumentNullException("rdfHandler", "Cannot use a null RDF Handler when the Query is a CONSTRUCT/DESCRIBE"); } if (resultsHandler == null && (query.QueryType == SparqlQueryType.Ask || SparqlSpecsHelper.IsSelectQuery(query.QueryType))) { throw new ArgumentNullException("resultsHandler", "Cannot use a null resultsHandler when the Query is an ASK/SELECT"); } //Handle the Thread Safety of the Query Evaluation #if !NO_RWLOCK ReaderWriterLockSlim currLock = (this._dataset is IThreadSafeDataset) ? ((IThreadSafeDataset)this._dataset).Lock : this._lock; try { currLock.EnterReadLock(); #endif //Reset Query Timers query.QueryExecutionTime = null; bool datasetOk = false, defGraphOk = false; try { //Set up the Default and Active Graphs if (query.DefaultGraphs.Any()) { //Call HasGraph() on each Default Graph but ignore the results, we just do this //in case a dataset has any kind of load on demand behaviour foreach (Uri defGraphUri in query.DefaultGraphs) { this._dataset.HasGraph(defGraphUri); } this._dataset.SetDefaultGraph(query.DefaultGraphs); defGraphOk = true; } else if (query.NamedGraphs.Any()) { //No FROM Clauses but one/more FROM NAMED means the Default Graph is the empty graph this._dataset.SetDefaultGraph(Enumerable.Empty <Uri>()); } this._dataset.SetActiveGraph(this._dataset.DefaultGraphUris); datasetOk = true; //Convert to Algebra and execute the Query SparqlEvaluationContext context = this.GetContext(query); BaseMultiset result; try { context.StartExecution(); ISparqlAlgebra algebra = query.ToAlgebra(); result = context.Evaluate(algebra); context.EndExecution(); query.QueryExecutionTime = new TimeSpan(context.QueryTimeTicks); } catch (RdfQueryException) { context.EndExecution(); query.QueryExecutionTime = new TimeSpan(context.QueryTimeTicks); throw; } catch { context.EndExecution(); query.QueryExecutionTime = new TimeSpan(context.QueryTimeTicks); throw; } //Return the Results switch (query.QueryType) { case SparqlQueryType.Ask: case SparqlQueryType.Select: case SparqlQueryType.SelectAll: case SparqlQueryType.SelectAllDistinct: case SparqlQueryType.SelectAllReduced: case SparqlQueryType.SelectDistinct: case SparqlQueryType.SelectReduced: //For SELECT and ASK can populate a Result Set directly from the Evaluation Context //return new SparqlResultSet(context); resultsHandler.Apply(context); break; case SparqlQueryType.Construct: //Create a new Empty Graph for the Results try { rdfHandler.StartRdf(); foreach (String prefix in query.NamespaceMap.Prefixes) { if (!rdfHandler.HandleNamespace(prefix, query.NamespaceMap.GetNamespaceUri(prefix))) { ParserHelper.Stop(); } } //Construct the Triples for each Solution foreach (ISet s in context.OutputMultiset.Sets) { //List<Triple> constructedTriples = new List<Triple>(); try { ConstructContext constructContext = new ConstructContext(rdfHandler, s, false); foreach (IConstructTriplePattern p in query.ConstructTemplate.TriplePatterns.OfType <IConstructTriplePattern>()) { try { if (!rdfHandler.HandleTriple(p.Construct(constructContext))) { ParserHelper.Stop(); } //constructedTriples.Add(((IConstructTriplePattern)p).Construct(constructContext)); } catch (RdfQueryException) { //If we get an error here then we could not construct a specific triple //so we continue anyway } } } catch (RdfQueryException) { //If we get an error here this means we couldn't construct for this solution so the //entire solution is discarded continue; } //h.Assert(constructedTriples); } rdfHandler.EndRdf(true); } catch (RdfParsingTerminatedException) { rdfHandler.EndRdf(true); } catch { rdfHandler.EndRdf(false); throw; } break; case SparqlQueryType.Describe: case SparqlQueryType.DescribeAll: //For DESCRIBE we retrieve the Describe algorithm and apply it ISparqlDescribe describer = query.Describer; describer.Describe(rdfHandler, context); break; default: throw new RdfQueryException("Unknown query types cannot be processed by Leviathan"); } } finally { if (defGraphOk) { this._dataset.ResetDefaultGraph(); } if (datasetOk) { this._dataset.ResetActiveGraph(); } } #if !NO_RWLOCK } finally { currLock.ExitReadLock(); } #endif }
/// <summary> /// Trims the Results of evaluating the inner pattern to remove Variables which are not Result Variables /// </summary> /// <param name="context">Evaluation Context</param> /// <returns></returns> public BaseMultiset Evaluate(SparqlEvaluationContext context) { try { context.InputMultiset = context.Evaluate(_pattern); } catch (RdfQueryTimeoutException) { // If not partial results throw the error if (context.Query == null || !context.Query.PartialResultsOnTimeout) { throw; } } // Ensure expected variables are present HashSet <SparqlVariable> vars = new HashSet <SparqlVariable>(_variables); if (context.InputMultiset is NullMultiset) { context.InputMultiset = new Multiset(vars.Select(v => v.Name)); } else if (context.InputMultiset is IdentityMultiset) { context.InputMultiset = new Multiset(vars.Select(v => v.Name)); context.InputMultiset.Add(new Set()); } else if (context.InputMultiset.IsEmpty) { foreach (SparqlVariable var in vars) { context.InputMultiset.AddVariable(var.Name); } } // Trim Variables that aren't being SELECTed if (!IsSelectAll) { foreach (String var in context.InputMultiset.Variables.ToList()) { if (!vars.Any(v => v.Name.Equals(var) && v.IsResultVariable)) { // If not a Result variable then trim from results context.InputMultiset.Trim(var); } } } // Ensure all SELECTed variables are present foreach (SparqlVariable var in vars) { if (!context.InputMultiset.ContainsVariable(var.Name)) { context.InputMultiset.AddVariable(var.Name); } } context.OutputMultiset = context.InputMultiset; // Apply variable ordering if applicable if (!IsSelectAll && (context.Query == null || SparqlSpecsHelper.IsSelectQuery(context.Query.QueryType))) { context.OutputMultiset.SetVariableOrder(context.Query.Variables.Where(v => v.IsResultVariable).Select(v => v.Name)); } return(context.OutputMultiset); }
public void SparqlBNodeValidation1() { Assert.True(SparqlSpecsHelper.IsValidBNode("_:a")); }