public static bool IsEquivalentTo(this ITypedElement left, ITypedElement right, bool compareNames = false) { if (compareNames && !namesAreEquivalent(left, right)) { return(false); } var l = left.Value; var r = right.Value; // TODO: this is actually a cast with knowledge of FHIR->System mappings, we don't want that here anymore // Convert quantities if (left.InstanceType == "Quantity" && l == null) { l = Typecasts.ParseQuantity(left); } if (right.InstanceType == "Quantity" && r == null) { r = Typecasts.ParseQuantity(right); } // Compare primitives (or extended primitives) // TODO: Define IsEquivalentTo for ALL datatypes in ITypedElement.value and move to Support assembly + test // TODO: Define on object, so this switch can be removed here // TODO: Move this IsEquivalentTo to the ElementModel assembly // Maybe create an interface? if (l != null && r != null) { return(Any.IsEquivalentTo(l, r)); } else if (l == null && r == null) { // Compare complex types (extensions on primitives are not compared, but handled (=ignored) above var childrenL = left.Children(); var childrenR = right.Children(); return(childrenL.IsEquivalentTo(childrenR, compareNames: true)); // NOTE: Assumes null will never be returned when any() children exist } else { // Else, we're comparing a complex (without a value) to a primitive which (probably) should return false return(false); } bool namesAreEquivalent(ITypedElement le, ITypedElement ri) { if (le.Name == "id" && ri.Name == "id") { return(true); // don't compare 'id' elements for equivalence } if (le.Name != ri.Name) { return(false); } return(true); } }
public static bool?IsEqualTo(this ITypedElement left, ITypedElement right, bool compareNames = false) { // If one or both of the arguments is an empty collection, a comparison operator will return an empty collection. // (though we might handle this more generally with the null-propagating functionality of the compiler // framework already. if (left is null || right is null) { return(null); } // TODO: Merge with ElementNodeComparator.IsEqualTo if (compareNames && (left.Name != right.Name)) { return(false); } var l = left.Value; var r = right.Value; // TODO: this is actually a cast with knowledge of FHIR->System mappings, we don't want that here anymore // Convert quantities if (left.InstanceType == "Quantity" && l == null) { l = Typecasts.ParseQuantity(left); } if (right.InstanceType == "Quantity" && r == null) { r = Typecasts.ParseQuantity(right); } // Compare primitives (or extended primitives) if (l != null && r != null && P.Any.TryConvert(l, out var lAny) && P.Any.TryConvert(r, out var rAny)) { return(IsEqualTo(lAny, rAny)); } else if (l == null && r == null) { // Compare complex types (extensions on primitives are not compared, but handled (=ignored) above var childrenL = left !.Children(); var childrenR = right !.Children(); return(childrenL.IsEqualTo(childrenR, compareNames: true)); // NOTE: Assumes null will never be returned when any() children exist } else { // Else, we're comparing a complex (without a value) to a primitive which (probably) should return false return(false); } }
public static bool IsEqualTo(this ITypedElement left, ITypedElement right, bool compareNames = false) { // TODO: Merge with ElementNodeComparator.IsEqualTo if (compareNames && (left.Name != right.Name)) { return(false); } var l = CastIntToLong(left.Value); var r = CastIntToLong(right.Value); // TODO: this is actually a cast with knowledge of FHIR->System mappings, we don't want that here anymore // Convert quantities if (left.InstanceType == "Quantity" && l == null) { l = Typecasts.ParseQuantity(left); } if (right.InstanceType == "Quantity" && r == null) { r = Typecasts.ParseQuantity(right); } // Compare primitives (or extended primitives) if (l != null && r != null) { return(Any.IsEqualTo(l, r)); } else if (l == null && r == null) { // Compare complex types (extensions on primitives are not compared, but handled (=ignored) above var childrenL = left.Children(); var childrenR = right.Children(); return(childrenL.IsEqualTo(childrenR, compareNames: true)); // NOTE: Assumes null will never be returned when any() children exist } else { // Else, we're comparing a complex (without a value) to a primitive which (probably) should return false return(false); } object CastIntToLong(object val) { // [MV 20200128] Because FhirPath works with longs, integers will be cast to longs return(val?.GetType() == typeof(int) ? Convert.ToInt64(val) : val); } }