/// <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)); } }