/// <summary> /// Creates a new Numeric Expression /// </summary> /// <param name="value">Float Value</param> public NumericExpressionTerm(float value) { this._type = SparqlNumericType.Float; this._fltvalue = (float)value; this._dblvalue = (double)value; this._value = new LiteralNode(null, this._dblvalue.ToString(), new Uri(XmlSpecsHelper.XmlSchemaDataTypeFloat)); }
/// <summary> /// Gets the numeric value of the function in the given Evaluation Context for the given Binding ID /// </summary> /// <param name="context">Evaluation Context</param> /// <param name="bindingID">Binding ID</param> /// <returns></returns> public override IValuedNode Evaluate(SparqlEvaluationContext context, int bindingID) { IValuedNode a = _leftExpr.Evaluate(context, bindingID); IValuedNode b = _rightExpr.Evaluate(context, bindingID); SparqlNumericType type = (SparqlNumericType)Math.Max((int)a.NumericType, (int)b.NumericType); switch (type) { case SparqlNumericType.Integer: return(new LongNode(null, Math.Max(a.AsInteger(), b.AsInteger()))); case SparqlNumericType.Decimal: return(new DecimalNode(null, Math.Max(a.AsDecimal(), b.AsDecimal()))); case SparqlNumericType.Float: return(new FloatNode(null, Math.Max(a.AsFloat(), b.AsFloat()))); case SparqlNumericType.Double: return(new DoubleNode(null, Math.Max(a.AsDouble(), b.AsDouble()))); default: throw new RdfQueryException("Cannot evalute an Arithmetic Expression when the Numeric Type of the expression cannot be determined"); } }
/// <summary> /// Calculates the Numeric 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 object NumericValue(SparqlEvaluationContext context, int bindingID) { if (this._leftExpr is ISparqlNumericExpression && this._rightExpr is ISparqlNumericExpression) { ISparqlNumericExpression a, b; a = (ISparqlNumericExpression)this._leftExpr; b = (ISparqlNumericExpression)this._rightExpr; SparqlNumericType type = (SparqlNumericType)Math.Max((int)a.NumericType(context, bindingID), (int)b.NumericType(context, bindingID)); switch (type) { case SparqlNumericType.Integer: return(a.IntegerValue(context, bindingID) + b.IntegerValue(context, bindingID)); case SparqlNumericType.Decimal: return(a.DecimalValue(context, bindingID) + b.DecimalValue(context, bindingID)); case SparqlNumericType.Float: return(a.FloatValue(context, bindingID) + b.FloatValue(context, bindingID)); case SparqlNumericType.Double: return(a.DoubleValue(context, bindingID) + b.DoubleValue(context, bindingID)); default: throw new RdfQueryException("Cannot evalute an Arithmetic Expression when the Numeric Type of the expression cannot be determined"); } } else { throw new RdfQueryException("Cannot evalute an Arithmetic Expression where the two sub-expressions are not Numeric Expressions"); } }
/// <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 virtual int NumericCompare(IValuedNode x, IValuedNode 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"); } switch (type) { case SparqlNumericType.Decimal: return(x.AsDecimal().CompareTo(y.AsDecimal())); case SparqlNumericType.Double: return(x.AsDouble().CompareTo(y.AsDouble())); case SparqlNumericType.Float: return(x.AsFloat().CompareTo(y.AsFloat())); case SparqlNumericType.Integer: return(x.AsInteger().CompareTo(y.AsInteger())); default: throw new RdfQueryException("Cannot evaluate numeric equality since of the arguments is not numeric"); } }
/// <summary> /// Gets the Numeric Value of the Function as evaluated in the given Context for the given Binding ID /// </summary> /// <param name="context">Evaluation Context</param> /// <param name="bindingID">Binding ID</param> /// <returns></returns> public override object NumericValue(SparqlEvaluationContext context, int bindingID) { if (this._expr is ISparqlNumericExpression) { ISparqlNumericExpression a = (ISparqlNumericExpression)this._expr; SparqlNumericType type = a.NumericType(context, bindingID); switch (type) { case SparqlNumericType.Integer: return(this.IntegerValueInternal(a.IntegerValue(context, bindingID))); case SparqlNumericType.Decimal: return(this.DecimalValueInternal(a.DecimalValue(context, bindingID))); case SparqlNumericType.Double: return(this.DoubleValueInternal(a.DoubleValue(context, bindingID))); case SparqlNumericType.NaN: default: throw new RdfQueryException("Unable to evaluate a Leviathan Numeric Expression since the inner expression did not evaluate to a Numeric Value"); } } else { throw new RdfQueryException("Unable to evaluate a Leviathan Numeric Expression since the inner expression is not a Numeric Expression"); } }
/// <summary> /// Gets the Numeric Value of the Function as evaluated in the given Context for the given Binding ID /// </summary> /// <param name="context">Evaluation Context</param> /// <param name="bindingID">Binding ID</param> /// <returns></returns> public override object NumericValue(SparqlEvaluationContext context, int bindingID) { if (this._leftExpr is ISparqlNumericExpression && this._rightExpr is ISparqlNumericExpression) { ISparqlNumericExpression a = (ISparqlNumericExpression)this._leftExpr; ISparqlNumericExpression b = (ISparqlNumericExpression)this._rightExpr; SparqlNumericType type = (SparqlNumericType)Math.Max((int)a.NumericType(context, bindingID), (int)b.NumericType(context, bindingID)); switch (type) { case SparqlNumericType.Integer: return(this.IntegerValueInternal(a.IntegerValue(context, bindingID), b.IntegerValue(context, bindingID))); case SparqlNumericType.Decimal: return(this.DecimalValueInternal(a.DecimalValue(context, bindingID), b.DecimalValue(context, bindingID))); case SparqlNumericType.Double: return(this.DoubleValueInternal(a.DoubleValue(context, bindingID), b.DoubleValue(context, bindingID))); case SparqlNumericType.NaN: default: throw new RdfQueryException("Unable to evaluate a Leviathan Numeric Expression since both arguments did not evaluate to a Numeric Value"); } } else { throw new RdfQueryException("Unable to evaluate a Leviathan Numeric Expression since the one/both of the arguments are not Numeric Expressions"); } }
/// <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> /// Applies the operator /// </summary> /// <param name="ns">Arguments</param> /// <returns></returns> public override IValuedNode Apply(params IValuedNode[] ns) { if (ns == null) { throw new RdfQueryException("Cannot apply to null arguments"); } if (ns.Any(n => n == null)) { throw new RdfQueryException("Cannot apply multiplication when any arguments are null"); } SparqlNumericType type = (SparqlNumericType)ns.Max(n => (int)n.NumericType); switch (type) { case SparqlNumericType.Integer: return(new LongNode(null, this.Multiply(ns.Select(n => n.AsInteger())))); case SparqlNumericType.Decimal: return(new DecimalNode(null, this.Multiply(ns.Select(n => n.AsDecimal())))); case SparqlNumericType.Float: return(new FloatNode(null, this.Multiply(ns.Select(n => n.AsFloat())))); case SparqlNumericType.Double: return(new DoubleNode(null, this.Multiply(ns.Select(n => n.AsDouble())))); default: throw new RdfQueryException("Cannot evalute an Arithmetic Expression when the Numeric Type of the expression cannot be determined"); } }
/// <summary> /// Calculates the Numeric 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 Object NumericValue(SparqlEvaluationContext context, int bindingID) { if (this._leftExpr is ISparqlNumericExpression && this._rightExpr is ISparqlNumericExpression) { ISparqlNumericExpression a, b; a = (ISparqlNumericExpression)this._leftExpr; b = (ISparqlNumericExpression)this._rightExpr; SparqlNumericType type = (SparqlNumericType)Math.Max((int)a.NumericType(context, bindingID), (int)b.NumericType(context, bindingID)); try { switch (type) { case SparqlNumericType.Integer: case SparqlNumericType.Decimal: //For Division Integers are treated as decimals decimal d = a.DecimalValue(context, bindingID) / b.DecimalValue(context, bindingID); if (Decimal.Floor(d).Equals(d) && d >= Int64.MinValue && d <= Int64.MaxValue) { return(Convert.ToInt64(d)); } return(d); case SparqlNumericType.Float: return(a.FloatValue(context, bindingID) / b.FloatValue(context, bindingID)); case SparqlNumericType.Double: return(a.DoubleValue(context, bindingID) / b.DoubleValue(context, bindingID)); default: throw new RdfQueryException("Cannot evalute an Arithmetic Expression when the Numeric Type of the expression cannot be determined"); } } catch (DivideByZeroException) { throw new RdfQueryException("Cannot evaluate a Division Expression where the divisor is Zero"); } } else { throw new RdfQueryException("Cannot evalute an Arithmetic Expression where the two sub-expressions are not Numeric Expressions"); } }
/// <summary> /// Calculates the Numeric 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 IValuedNode Evaluate(SparqlEvaluationContext context, int bindingID) { IValuedNode a = this._leftExpr.Evaluate(context, bindingID); IValuedNode b = this._rightExpr.Evaluate(context, bindingID); if (a == null || b == null) { throw new RdfQueryException("Cannot apply division when one/both arguments are null"); } SparqlNumericType type = (SparqlNumericType)Math.Max((int)a.NumericType, (int)b.NumericType); try { switch (type) { case SparqlNumericType.Integer: case SparqlNumericType.Decimal: //For Division Integers are treated as decimals decimal d = a.AsDecimal() / b.AsDecimal(); if (Decimal.Floor(d).Equals(d) && d >= Int64.MinValue && d <= Int64.MaxValue) { return(new LongNode(null, Convert.ToInt64(d))); } return(new DecimalNode(null, d)); case SparqlNumericType.Float: return(new FloatNode(null, a.AsFloat() / b.AsFloat())); case SparqlNumericType.Double: return(new DoubleNode(null, a.AsDouble() / b.AsDouble())); default: throw new RdfQueryException("Cannot evalute an Arithmetic Expression when the Numeric Type of the expression cannot be determined"); } } catch (DivideByZeroException) { throw new RdfQueryException("Cannot evaluate a Division Expression where the divisor is Zero"); } }
/// <summary> /// Applies the operator /// </summary> /// <param name="ns">Arguments</param> /// <returns></returns> public override IValuedNode Apply(params IValuedNode[] ns) { if (ns.Any(n => n == null)) { throw new RdfQueryException("Cannot apply division when any arguments are null"); } SparqlNumericType type = (SparqlNumericType)ns.Max(n => (int)n.NumericType); try { switch (type) { case SparqlNumericType.Integer: case SparqlNumericType.Decimal: // For Division Integers are treated as decimals decimal d = this.Divide(ns.Select(n => n.AsDecimal())); if (Decimal.Floor(d).Equals(d) && d >= Int64.MinValue && d <= Int64.MaxValue) { return(new LongNode(null, Convert.ToInt64(d))); } return(new DecimalNode(null, d)); case SparqlNumericType.Float: return(new FloatNode(null, this.Divide(ns.Select(n => n.AsFloat())))); case SparqlNumericType.Double: return(new DoubleNode(null, this.Divide(ns.Select(n => n.AsDouble())))); default: throw new RdfQueryException("Cannot evalute an Arithmetic Expression when the Numeric Type of the expression cannot be determined"); } } catch (DivideByZeroException) { throw new RdfQueryException("Cannot evaluate a Division Expression where the divisor is Zero"); } }
/// <summary> /// Applies the Average Aggregate function to the results /// </summary> /// <param name="context">Evaluation Context</param> /// <param name="bindingIDs">Binding IDs over which the aggregate applies</param> /// <returns></returns> public override INode Apply(SparqlEvaluationContext context, IEnumerable <int> bindingIDs) { if (this._varname != null) { //Ensured the AVGed variable is in the Variables of the Results if (!context.Binder.Variables.Contains(this._varname)) { throw new RdfQueryException("Cannot use the Variable " + this._expr.ToString() + " in a AVG Aggregate since the Variable does not occur in a Graph Pattern"); } } //Prep Variables HashSet <INode> values = new HashSet <INode>(); int count = 0; //long lngtotal = 0; decimal dectotal = 0.0m; float flttotal = 0.0f; double dbltotal = 0.0d; SparqlNumericType maxtype = SparqlNumericType.NaN; ISparqlNumericExpression numExpr; if (!(this._expr is ISparqlNumericExpression)) { numExpr = new NumericWrapperExpression(this._expr); //throw new RdfQueryException("Cannot calculate an average aggregate over a non-numeric expression"); } else { numExpr = (ISparqlNumericExpression)this._expr; } SparqlNumericType numtype; foreach (int id in bindingIDs) { try { //Apply DISTINCT modifier if required if (this._distinct) { INode temp = this._expr.Value(context, id); if (temp == null) { return(null); } if (values.Contains(temp)) { continue; } else { values.Add(temp); } } numtype = numExpr.NumericType(context, id); } catch { //SPARQL Working Group changed spec so this should now return no binding return(null); } //Skip if Not a Number if (numtype == SparqlNumericType.NaN) { return(null); } //Track the Numeric Type if ((int)numtype > (int)maxtype) { maxtype = numtype; } //Increment the Totals based on the current Numeric Type switch (maxtype) { case SparqlNumericType.Integer: //lngtotal += numExpr.IntegerValue(context, id); dectotal += numExpr.DecimalValue(context, id); flttotal += numExpr.FloatValue(context, id); dbltotal += numExpr.DoubleValue(context, id); break; case SparqlNumericType.Decimal: dectotal += numExpr.DecimalValue(context, id); flttotal += numExpr.FloatValue(context, id); dbltotal += numExpr.DoubleValue(context, id); break; case SparqlNumericType.Float: flttotal += numExpr.FloatValue(context, id); dbltotal += numExpr.DoubleValue(context, id); break; case SparqlNumericType.Double: dbltotal += numExpr.DoubleValue(context, id); break; } count++; } //Calculate the Average if (count == 0) { return(new LiteralNode(null, "0", new Uri(XmlSpecsHelper.XmlSchemaDataTypeInteger))); } else { //long lngavg; decimal decavg; float fltavg; double dblavg; switch (maxtype) { case SparqlNumericType.NaN: //No Numeric Values return(new LiteralNode(null, "0", new Uri(XmlSpecsHelper.XmlSchemaDataTypeInteger))); case SparqlNumericType.Integer: ////Integer Values //lngavg = lngtotal / (long)count; //return new LiteralNode(null, lngavg.ToString(), new Uri(XmlSpecsHelper.XmlSchemaDataTypeInteger)); case SparqlNumericType.Decimal: //Decimal Values decavg = dectotal / (decimal)count; return(new LiteralNode(null, decavg.ToString(), new Uri(XmlSpecsHelper.XmlSchemaDataTypeDecimal))); case SparqlNumericType.Float: //Float values fltavg = flttotal / (float)count; return(new LiteralNode(null, fltavg.ToString(), new Uri(XmlSpecsHelper.XmlSchemaDataTypeFloat))); case SparqlNumericType.Double: //Double Values dblavg = dbltotal / (double)count; return(new LiteralNode(null, dblavg.ToString(), new Uri(XmlSpecsHelper.XmlSchemaDataTypeDouble))); default: throw new RdfQueryException("Failed to calculate a valid Average"); } } }
/// <summary> /// Creates a new numeric valued node. /// </summary> /// <param name="g">Graph the node belongs to.</param> /// <param name="value">Lexical Value.</param> /// <param name="datatype">Datatype URI.</param> /// <param name="numType">SPARQL Numeric Type.</param> protected NumericNode(IGraph g, String value, Uri datatype, SparqlNumericType numType) : base(g, value, datatype) { _numType = numType; }
/// <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> /// Implements Numeric Equality with SPARQL Semantics /// </summary> /// <param name="x">Node</param> /// <param name="y">Node</param> /// <param name="type">SPARQL Numeric Tyoe</param> /// <returns></returns> public static bool NumericEquality(INode x, INode y, SparqlNumericType type) { if (x == null || y == null) throw new RdfQueryException("Cannot evaluate numeric equality when one or both arguments are Null"); if (type == SparqlNumericType.NaN) throw new RdfQueryException("Cannot evaluate numeric equality when the Numeric Type is NaN"); try { ILiteralNode a = (ILiteralNode)x; ILiteralNode b = (ILiteralNode)y; switch (type) { case SparqlNumericType.Decimal: return ToDecimal(a).Equals(ToDecimal(b)); case SparqlNumericType.Double: return ToDouble(a).Equals(ToDouble(b)); case SparqlNumericType.Float: return ToFloat(a).Equals(ToFloat(b)); case SparqlNumericType.Integer: return ToInteger(a).Equals(ToInteger(b)); default: throw new RdfQueryException("Cannot evaluate numeric equality since of the arguments is not numeric"); } } catch (FormatException) { throw;// new RdfQueryException("Cannot evaluate numeric equality since one of the arguments does not have a valid lexical value for the given type"); } }
/// <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> /// Compares two Nodes /// </summary> /// <param name="x">Node</param> /// <param name="y">Node</param> /// <returns></returns> public override int Compare(IValuedNode x, IValuedNode y) { // Nulls are less than everything if (x == null && y == null) { return(0); } if (x == null) { return(-1); } if (y == null) { return(1); } // If the Node Types are different use Node ordering if (x.NodeType != y.NodeType) { return(x.CompareTo(y)); } if (x.NodeType == NodeType.Literal) { try { // Do they have supported Data Types? String xtype, ytype; try { xtype = XmlSpecsHelper.GetSupportedDataType(x); ytype = XmlSpecsHelper.GetSupportedDataType(y); } catch (RdfException) { // Can't determine a Data Type for one/both of the Nodes so use Node ordering return(x.CompareTo(y)); } if (xtype.Equals(String.Empty) || ytype.Equals(String.Empty)) { // One/both has an unknown type if (x.Equals(y)) { // If RDF Term equality returns true then we return that they are equal return(0); } else { // If RDF Term equality returns false then we fall back to Node Ordering return(x.CompareTo(y)); } } else { // Both have known types SparqlNumericType xnumtype = x.NumericType; SparqlNumericType ynumtype = y.NumericType; SparqlNumericType numtype = (SparqlNumericType)Math.Max((int)xnumtype, (int)ynumtype); if (numtype != SparqlNumericType.NaN) { if (xnumtype == SparqlNumericType.NaN) { return(1); } else if (ynumtype == SparqlNumericType.NaN) { return(-1); } // Both are Numeric so use Numeric ordering try { return(this.NumericCompare(x, y, numtype)); } catch (FormatException) { if (x.Equals(y)) { return(0); } // Otherwise fall back to Node Ordering return(x.CompareTo(y)); } catch (RdfQueryException) { // If this errors try RDF Term equality since that might still give equality if (x.Equals(y)) { return(0); } // Otherwise fall back to Node Ordering return(x.CompareTo(y)); } } else if (xtype.Equals(ytype)) { switch (xtype) { case XmlSpecsHelper.XmlSchemaDataTypeDate: return(DateCompare(x, y)); case XmlSpecsHelper.XmlSchemaDataTypeDateTime: return(DateTimeCompare(x, y)); case XmlSpecsHelper.XmlSchemaDataTypeString: // Both Strings so use Lexical string ordering return(((ILiteralNode)x).Value.CompareTo(((ILiteralNode)y).Value)); default: // Use node ordering return(x.CompareTo(y)); } } else { String commontype = XmlSpecsHelper.GetCompatibleSupportedDataType(xtype, ytype, true); if (commontype.Equals(String.Empty)) { // Use Node ordering return(x.CompareTo(y)); } else { switch (commontype) { case XmlSpecsHelper.XmlSchemaDataTypeDate: return(DateCompare(x, y)); case XmlSpecsHelper.XmlSchemaDataTypeDateTime: return(DateTimeCompare(x, y)); default: // Use Node ordering return(x.CompareTo(y)); } } } } } catch { // If error then can't determine ordering so fall back to node ordering return(x.CompareTo(y)); } } else { // If not Literals use Node ordering return(x.CompareTo(y)); } }
/// <summary> /// Compares two Nodes /// </summary> /// <param name="x">Node</param> /// <param name="y">Node</param> /// <returns></returns> public virtual int Compare(INode x, INode y) { // Nulls are less than everything if (x == null && y == null) { return(0); } if (x == null) { return(-1); } if (y == null) { return(1); } // If the Node Types are different use Node ordering if (x.NodeType != y.NodeType) { return(x.CompareTo(y)); } if (x.NodeType == NodeType.Literal) { // Do they have supported Data Types? String xtype, ytype; try { xtype = XmlSpecsHelper.GetSupportedDataType(x); ytype = XmlSpecsHelper.GetSupportedDataType(y); } catch (RdfException) { // Can't determine a Data Type for one/both of the Nodes so use Node ordering return(x.CompareTo(y)); } if (xtype.Equals(String.Empty) || ytype.Equals(String.Empty)) { // One/both has an unknown type if (x.Equals(y)) { // If RDF Term equality returns true then we return that they are equal return(0); } else { // If RDF Term equality returns false then we error // UNLESS they have the same Datatype throw new RdfQueryException("Unable to determine ordering since one/both arguments has an Unknown Type"); } } else { // Both have known types SparqlNumericType xnumtype = SparqlSpecsHelper.GetNumericTypeFromDataTypeUri(xtype); SparqlNumericType ynumtype = SparqlSpecsHelper.GetNumericTypeFromDataTypeUri(ytype); SparqlNumericType numtype = (SparqlNumericType)Math.Max((int)xnumtype, (int)ynumtype); if (numtype != SparqlNumericType.NaN) { if (xnumtype == SparqlNumericType.NaN || ynumtype == SparqlNumericType.NaN) { // If one is non-numeric then we can't assume non-equality throw new RdfQueryException("Unable to determine ordering since one/both arguments does not return a Number"); } // Both are Numeric so use Numeric ordering try { return(this.NumericCompare(x, y, numtype)); } catch (FormatException) { if (x.Equals(y)) { return(0); } throw new RdfQueryException("Unable to determine ordering since one/both arguments does not contain a valid value for it's type"); } catch (RdfQueryException) { // If this errors try RDF Term equality since if (x.Equals(y)) { return(0); } throw new RdfQueryException("Unable to determine ordering since one/both arguments was not a valid numeric"); } } else if (xtype.Equals(ytype)) { switch (xtype) { case XmlSpecsHelper.XmlSchemaDataTypeDate: return(DateCompare(x, y)); case XmlSpecsHelper.XmlSchemaDataTypeDateTime: return(DateTimeCompare(x, y)); case XmlSpecsHelper.XmlSchemaDataTypeString: // Both Strings so use Lexical string ordering #if NETCORE return(Options.DefaultCulture.CompareInfo.Compare(((ILiteralNode)x).Value, ((ILiteralNode)y).Value, Options.DefaultComparisonOptions)); #else return(String.Compare(((ILiteralNode)x).Value, ((ILiteralNode)y).Value, Options.DefaultCulture, Options.DefaultComparisonOptions)); #endif default: // Use node ordering return(x.CompareTo(y)); } } else { String commontype = XmlSpecsHelper.GetCompatibleSupportedDataType(xtype, ytype, true); if (commontype.Equals(String.Empty)) { // Use Node ordering return(x.CompareTo(y)); } else { switch (commontype) { case XmlSpecsHelper.XmlSchemaDataTypeDate: return(DateCompare(x, y)); case XmlSpecsHelper.XmlSchemaDataTypeDateTime: return(DateTimeCompare(x, y)); default: // Use Node ordering return(x.CompareTo(y)); } } } } } else { // If not Literals use Node ordering return(x.CompareTo(y)); } }
/// <summary> /// Creates a new Numeric Expression /// </summary> /// <param name = "value">Integer Value</param> public NumericExpressionTerm(long value) { _type = SparqlNumericType.Integer; _intvalue = value; _decvalue = value; _fltvalue = value; _dblvalue = value; _value = new LiteralNode(null, _intvalue.ToString(), new Uri(XmlSpecsHelper.XmlSchemaDataTypeInteger)); }
/// <summary> /// Creates a new Numeric Expression /// </summary> /// <param name = "value">Decimal Value</param> public NumericExpressionTerm(decimal value) { _type = SparqlNumericType.Decimal; _decvalue = value; _fltvalue = (float) value; _dblvalue = (double) value; _value = new LiteralNode(null, _decvalue.ToString(), new Uri(XmlSpecsHelper.XmlSchemaDataTypeDecimal)); }
/// <summary> /// Creates a new Numeric Expression /// </summary> /// <param name = "value">Float Value</param> public NumericExpressionTerm(float value) { _type = SparqlNumericType.Float; _fltvalue = value; _dblvalue = value; _value = new LiteralNode(null, _dblvalue.ToString(), new Uri(XmlSpecsHelper.XmlSchemaDataTypeFloat)); }
/// <summary> /// Applies the Numeric Min Aggregate function to the results /// </summary> /// <param name="context">Evaluation Context</param> /// <param name="bindingIDs">Binding IDs over which the Aggregate applies</param> /// <returns></returns> public override INode Apply(SparqlEvaluationContext context, IEnumerable <int> bindingIDs) { if (this._varname != null) { //Ensured the MINed variable is in the Variables of the Results if (!context.Binder.Variables.Contains(this._varname)) { throw new RdfQueryException("Cannot use the Variable " + this._expr.ToString() + " in a NMIN Aggregate since the Variable does not occur in a Graph Pattern"); } } //Prep Variables long lngmin = 0; decimal decmin = 0.0m; float fltmin = 0.0f; double dblmin = 0.0d; SparqlNumericType mintype = SparqlNumericType.NaN; if (!(this._expr is ISparqlNumericExpression)) { throw new RdfQueryException("Cannot evaluate a NMIN aggregate over a non-numeric expression"); } ISparqlNumericExpression numExpr = (ISparqlNumericExpression)this._expr; SparqlNumericType numtype; foreach (int id in bindingIDs) { try { numtype = numExpr.NumericType(context, id); } catch { continue; } //Skip if Not a Number if (numtype == SparqlNumericType.NaN) { continue; } //Track the Numeric Type if ((int)numtype > (int)mintype) { if (mintype == SparqlNumericType.NaN) { //Initialise Minimums switch (numtype) { case SparqlNumericType.Integer: lngmin = numExpr.IntegerValue(context, id); decmin = numExpr.DecimalValue(context, id); fltmin = numExpr.FloatValue(context, id); dblmin = numExpr.DoubleValue(context, id); break; case SparqlNumericType.Decimal: decmin = numExpr.DecimalValue(context, id); fltmin = numExpr.FloatValue(context, id); dblmin = numExpr.DoubleValue(context, id); break; case SparqlNumericType.Float: fltmin = numExpr.FloatValue(context, id); dblmin = numExpr.DoubleValue(context, id); break; case SparqlNumericType.Double: dblmin = numExpr.DoubleValue(context, id); break; } mintype = numtype; continue; } else { mintype = numtype; } } long lngval; decimal decval; float fltval; double dblval; switch (mintype) { case SparqlNumericType.Integer: lngval = numExpr.IntegerValue(context, id); if (lngval < lngmin) { lngmin = lngval; decmin = numExpr.DecimalValue(context, id); fltmin = numExpr.FloatValue(context, id); dblmin = numExpr.DoubleValue(context, id); } break; case SparqlNumericType.Decimal: decval = numExpr.DecimalValue(context, id); if (decval < decmin) { decmin = decval; fltmin = numExpr.FloatValue(context, id); dblmin = numExpr.DoubleValue(context, id); } break; case SparqlNumericType.Float: fltval = numExpr.FloatValue(context, id); if (fltval < fltmin) { fltmin = fltval; dblmin = numExpr.DoubleValue(context, id); } break; case SparqlNumericType.Double: dblval = numExpr.DoubleValue(context, id); if (dblval < dblmin) { dblmin = dblval; } break; } } //Return the Min switch (mintype) { case SparqlNumericType.NaN: //No Numeric Values return(null); case SparqlNumericType.Integer: //Integer Values return(new LiteralNode(null, lngmin.ToString(), new Uri(XmlSpecsHelper.XmlSchemaDataTypeInteger))); case SparqlNumericType.Decimal: //Decimal Values return(new LiteralNode(null, decmin.ToString(), new Uri(XmlSpecsHelper.XmlSchemaDataTypeDecimal))); case SparqlNumericType.Double: //Double Values return(new LiteralNode(null, dblmin.ToString(), new Uri(XmlSpecsHelper.XmlSchemaDataTypeDouble))); default: throw new RdfQueryException("Failed to calculate a valid Minimum"); } }
/// <summary> /// Applies the Sum Aggregate function to the results /// </summary> /// <param name="context">Evaluation Context</param> /// <param name="bindingIDs">Binding IDs over which the Aggregate applies</param> /// <returns></returns> public override INode Apply(SparqlEvaluationContext context, IEnumerable <int> bindingIDs) { if (this._varname != null) { //Ensured the SUMmed variable is in the Variables of the Results if (!context.Binder.Variables.Contains(this._varname)) { throw new RdfQueryException("Cannot use the Variable " + this._expr.ToString() + " in a SUM Aggregate since the Variable does not occur in a Graph Pattern"); } } //Prep Variables long lngtotal = 0; decimal dectotal = 0.0m; float flttotal = 0.0f; double dbltotal = 0.0d; SparqlNumericType maxtype = SparqlNumericType.NaN; if (!(this._expr is ISparqlNumericExpression)) { throw new RdfQueryException("Cannot calculate an sum aggregate over a non-numeric expression"); } ISparqlNumericExpression numExpr = (ISparqlNumericExpression)this._expr; SparqlNumericType numtype; HashSet <INode> values = new HashSet <INode>(); foreach (int id in bindingIDs) { try { if (this._distinct) { INode temp = this._expr.Value(context, id); if (temp == null) { continue; } if (values.Contains(temp)) { continue; } else { values.Add(temp); } } numtype = numExpr.NumericType(context, id); } catch { continue; } //Skip if Not a Number if (numtype == SparqlNumericType.NaN) { continue; } //Track the Numeric Type if ((int)numtype > (int)maxtype) { maxtype = numtype; } //Increment the Totals based on the current Numeric Type switch (maxtype) { case SparqlNumericType.Integer: lngtotal += numExpr.IntegerValue(context, id); dectotal += numExpr.DecimalValue(context, id); flttotal += numExpr.FloatValue(context, id); dbltotal += numExpr.DoubleValue(context, id); break; case SparqlNumericType.Decimal: dectotal += numExpr.DecimalValue(context, id); flttotal += numExpr.FloatValue(context, id); dbltotal += numExpr.DoubleValue(context, id); break; case SparqlNumericType.Float: flttotal += numExpr.FloatValue(context, id); dbltotal += numExpr.DoubleValue(context, id); break; case SparqlNumericType.Double: dbltotal += numExpr.DoubleValue(context, id); break; } } //Return the Sum switch (maxtype) { case SparqlNumericType.NaN: //No Numeric Values return(new LiteralNode(null, "0", new Uri(XmlSpecsHelper.XmlSchemaDataTypeInteger))); case SparqlNumericType.Integer: //Integer Values return(new LiteralNode(null, lngtotal.ToString(), new Uri(XmlSpecsHelper.XmlSchemaDataTypeInteger))); case SparqlNumericType.Decimal: //Decimal Values return(new LiteralNode(null, dectotal.ToString(), new Uri(XmlSpecsHelper.XmlSchemaDataTypeDecimal))); case SparqlNumericType.Float: //Float Values return(new LiteralNode(null, flttotal.ToString(), new Uri(XmlSpecsHelper.XmlSchemaDataTypeFloat))); case SparqlNumericType.Double: //Double Values return(new LiteralNode(null, dbltotal.ToString(), new Uri(XmlSpecsHelper.XmlSchemaDataTypeDouble))); default: throw new RdfQueryException("Failed to calculate a valid Sum"); } }
/// <summary> /// Creates a new Numeric Expression /// </summary> /// <param name = "value">Double Value</param> public NumericExpressionTerm(double value) { _type = SparqlNumericType.Double; _dblvalue = value; _value = new LiteralNode(null, _dblvalue.ToString(), new Uri(XmlSpecsHelper.XmlSchemaDataTypeDouble)); }
/// <summary> /// Applies the Sum Aggregate function to the results. /// </summary> /// <param name="context">Evaluation Context.</param> /// <param name="bindingIDs">Binding IDs over which the Aggregate applies.</param> /// <returns></returns> public override IValuedNode Apply(SparqlEvaluationContext context, IEnumerable <int> bindingIDs) { // Prep Variables long lngtotal = 0; decimal dectotal = 0.0m; float flttotal = 0.0f; double dbltotal = 0.0d; SparqlNumericType maxtype = SparqlNumericType.NaN; SparqlNumericType numtype; HashSet <IValuedNode> values = new HashSet <IValuedNode>(); foreach (int id in bindingIDs) { IValuedNode temp; try { temp = _expr.Evaluate(context, id); if (_distinct) { if (temp == null) { continue; } if (values.Contains(temp)) { continue; } else { values.Add(temp); } } numtype = temp.NumericType; } catch { continue; } // Skip if Not a Number if (numtype == SparqlNumericType.NaN) { continue; } // Track the Numeric Type if ((int)numtype > (int)maxtype) { maxtype = numtype; } // Increment the Totals based on the current Numeric Type switch (maxtype) { case SparqlNumericType.Integer: lngtotal += temp.AsInteger(); dectotal += temp.AsDecimal(); flttotal += temp.AsFloat(); dbltotal += temp.AsDouble(); break; case SparqlNumericType.Decimal: dectotal += temp.AsDecimal(); flttotal += temp.AsFloat(); dbltotal += temp.AsDouble(); break; case SparqlNumericType.Float: flttotal += temp.AsFloat(); dbltotal += temp.AsDouble(); break; case SparqlNumericType.Double: dbltotal += temp.AsDouble(); break; } } // Return the Sum switch (maxtype) { case SparqlNumericType.NaN: // No Numeric Values return(new LongNode(null, 0)); case SparqlNumericType.Integer: // Integer Values return(new LongNode(null, lngtotal)); case SparqlNumericType.Decimal: // Decimal Values return(new DecimalNode(null, dectotal)); case SparqlNumericType.Float: // Float Values return(new FloatNode(null, flttotal)); case SparqlNumericType.Double: // Double Values return(new DoubleNode(null, dbltotal)); default: throw new RdfQueryException("Failed to calculate a valid Sum"); } }
/// <summary> /// Applies the Average Aggregate function to the results /// </summary> /// <param name="context">Evaluation Context</param> /// <param name="bindingIDs">Binding IDs over which the aggregate applies</param> /// <returns></returns> public override IValuedNode Apply(SparqlEvaluationContext context, IEnumerable <int> bindingIDs) { //Prep Variables HashSet <IValuedNode> values = new HashSet <IValuedNode>(); int count = 0; //long lngtotal = 0; decimal dectotal = 0.0m; float flttotal = 0.0f; double dbltotal = 0.0d; SparqlNumericType maxtype = SparqlNumericType.NaN; SparqlNumericType numtype; foreach (int id in bindingIDs) { IValuedNode temp; try { temp = this._expr.Evaluate(context, id); if (temp == null) { return(null); } //Apply DISTINCT modifier if required if (this._distinct) { if (values.Contains(temp)) { continue; } else { values.Add(temp); } } numtype = temp.NumericType; } catch { //SPARQL Working Group changed spec so this should now return no binding return(null); } //No result if anything resolves to non-numeric if (numtype == SparqlNumericType.NaN) { return(null); } //Track the Numeric Type if ((int)numtype > (int)maxtype) { maxtype = numtype; } //Increment the Totals based on the current Numeric Type switch (maxtype) { case SparqlNumericType.Integer: //lngtotal += numExpr.IntegerValue(context, id); dectotal += temp.AsDecimal(); flttotal += temp.AsFloat(); dbltotal += temp.AsDouble(); break; case SparqlNumericType.Decimal: dectotal += temp.AsDecimal(); flttotal += temp.AsFloat(); dbltotal += temp.AsDouble(); break; case SparqlNumericType.Float: flttotal += temp.AsFloat(); dbltotal += temp.AsDouble(); break; case SparqlNumericType.Double: dbltotal += temp.AsDouble(); break; } count++; } //Calculate the Average if (count == 0) { return(new LongNode(null, 0)); } else { //long lngavg; decimal decavg; float fltavg; double dblavg; switch (maxtype) { case SparqlNumericType.Integer: ////Integer Values //lngavg = lngtotal / (long)count; //return new LiteralNode(null, lngavg.ToString(), new Uri(XmlSpecsHelper.XmlSchemaDataTypeInteger)); case SparqlNumericType.Decimal: //Decimal Values decavg = dectotal / (decimal)count; return(new DecimalNode(null, decavg)); case SparqlNumericType.Float: //Float values fltavg = flttotal / (float)count; return(new FloatNode(null, fltavg)); case SparqlNumericType.Double: //Double Values dblavg = dbltotal / (double)count; return(new DoubleNode(null, dblavg)); default: throw new RdfQueryException("Failed to calculate a valid Average"); } } }
/// <summary> /// Creates a new numeric valued node /// </summary> /// <param name="g">Graph the node belongs to</param> /// <param name="value">Lexical Value</param> /// <param name="datatype">Datatype URI</param> /// <param name="numType">SPARQL Numeric Type</param> public NumericNode(IGraph g, String value, Uri datatype, SparqlNumericType numType) : base(g, value, datatype) { this._numType = numType; }
/// <summary> /// Applies the Numeric Max Aggregate function to the results /// </summary> /// <param name="context">Evaluation Context</param> /// <param name="bindingIDs">Binding IDs over which the Aggregate applies</param> /// <returns></returns> public override IValuedNode Apply(SparqlEvaluationContext context, IEnumerable <int> bindingIDs) { if (_varname != null) { // Ensured the MAXed variable is in the Variables of the Results if (!context.Binder.Variables.Contains(_varname)) { throw new RdfQueryException("Cannot use the Variable " + _expr.ToString() + " in a NMAX Aggregate since the Variable does not occur in a Graph Pattern"); } } // Prep Variables long lngmax = 0; decimal decmax = 0.0m; float fltmax = 0.0f; double dblmax = 0.0d; SparqlNumericType maxtype = SparqlNumericType.NaN; SparqlNumericType numtype; foreach (int id in bindingIDs) { IValuedNode temp; try { temp = _expr.Evaluate(context, id); if (temp == null) { continue; } numtype = temp.NumericType; } catch { continue; } // Skip if Not a Number if (numtype == SparqlNumericType.NaN) { continue; } // Track the Numeric Type if ((int)numtype > (int)maxtype) { if (maxtype == SparqlNumericType.NaN) { // Initialise Maximums switch (numtype) { case SparqlNumericType.Integer: lngmax = temp.AsInteger(); decmax = temp.AsDecimal(); fltmax = temp.AsFloat(); dblmax = temp.AsDouble(); break; case SparqlNumericType.Decimal: decmax = temp.AsDecimal(); fltmax = temp.AsFloat(); dblmax = temp.AsDouble(); break; case SparqlNumericType.Float: fltmax = temp.AsFloat(); dblmax = temp.AsDouble(); break; case SparqlNumericType.Double: dblmax = temp.AsDouble(); break; } maxtype = numtype; continue; } else { maxtype = numtype; } } long lngval; decimal decval; float fltval; double dblval; switch (maxtype) { case SparqlNumericType.Integer: lngval = temp.AsInteger(); if (lngval > lngmax) { lngmax = lngval; decmax = temp.AsDecimal(); fltmax = temp.AsFloat(); dblmax = temp.AsDouble(); } break; case SparqlNumericType.Decimal: decval = temp.AsDecimal(); if (decval > decmax) { decmax = decval; fltmax = temp.AsFloat(); dblmax = temp.AsDouble(); } break; case SparqlNumericType.Float: fltval = temp.AsFloat(); if (fltval > fltmax) { fltmax = fltval; dblmax = temp.AsDouble(); } break; case SparqlNumericType.Double: dblval = temp.AsDouble(); if (dblval > dblmax) { dblmax = dblval; } break; } } // Return the Max switch (maxtype) { case SparqlNumericType.NaN: // No Numeric Values return(null); case SparqlNumericType.Integer: // Integer Values return(new LongNode(null, lngmax)); case SparqlNumericType.Decimal: // Decimal Values return(new DecimalNode(null, decmax)); case SparqlNumericType.Float: // Float values return(new FloatNode(null, fltmax)); case SparqlNumericType.Double: // Double Values return(new DoubleNode(null, dblmax)); default: throw new RdfQueryException("Failed to calculate a valid Maximum"); } }
/// <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 virtual int NumericCompare(INode x, INode y, SparqlNumericType type) { return(NumericCompare(x.AsValuedNode(), y.AsValuedNode(), type)); }
/// <summary> /// Creates a new Numeric Expression /// </summary> /// <param name="value">Double Value</param> public NumericExpressionTerm(double value) { this._type = SparqlNumericType.Double; this._dblvalue = value; this._value = new LiteralNode(null, this._dblvalue.ToString(), new Uri(XmlSpecsHelper.XmlSchemaDataTypeDouble)); }
/// <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 INode Value(SparqlEvaluationContext context, int bindingID) { INode n = this._expr.Value(context, bindingID); if (n == null) { throw new RdfQueryException("Cannot cast a Null to a xsd:boolean"); } 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 ILiteralNode lit = (ILiteralNode)n; if (lit.DataType != null) { String dt = lit.DataType.ToString(); if (dt.Equals(XmlSpecsHelper.XmlSchemaDataTypeBoolean)) { //Already a Boolean return(lit); } //Cast based on Numeric Type SparqlNumericType type = SparqlSpecsHelper.GetNumericTypeFromDataTypeUri(dt); switch (type) { case SparqlNumericType.Decimal: Decimal dec; if (Decimal.TryParse(lit.Value, out dec)) { if (dec.Equals(Decimal.Zero)) { return(new LiteralNode(lit.Graph, "false", new Uri(XmlSpecsHelper.XmlSchemaDataTypeBoolean))); } else { return(new LiteralNode(lit.Graph, "true", new Uri(XmlSpecsHelper.XmlSchemaDataTypeBoolean))); } } 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, out dbl)) { if (Double.IsNaN(dbl) || dbl == 0.0d) { return(new LiteralNode(lit.Graph, "false", new Uri(XmlSpecsHelper.XmlSchemaDataTypeBoolean))); } else { return(new LiteralNode(lit.Graph, "true", new Uri(XmlSpecsHelper.XmlSchemaDataTypeBoolean))); } } 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 LiteralNode(lit.Graph, "false", new Uri(XmlSpecsHelper.XmlSchemaDataTypeBoolean))); } else { return(new LiteralNode(lit.Graph, "true", new Uri(XmlSpecsHelper.XmlSchemaDataTypeBoolean))); } } 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 LiteralNode(lit.Graph, b.ToString(), new Uri(XmlSpecsHelper.XmlSchemaDataTypeBoolean))); } 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 LiteralNode(lit.Graph, b.ToString(), new Uri(XmlSpecsHelper.XmlSchemaDataTypeBoolean))); } 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"); } }