/// <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 = this._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, 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, 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> /// 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(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> /// 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"); } }