/// <summary> /// Compares two HierarchyIds by their values. /// </summary> /// <param name="hid1"> a HierarchyId to compare </param> /// <param name="hid2"> a HierarchyId to compare </param> /// <returns> /// A 32-bit signed integer that indicates the lexical relationship between the two comparands. /// Value Condition Less than zero: hid1 is less than hid2. /// Zero: hid1 equals hid2. /// Greater than zero: hid1 is greater than hid2. /// </returns> public static int Compare(HierarchyId hid1, HierarchyId hid2) { var nodes1 = hid1.GetNodes(); var nodes2 = hid2.GetNodes(); int count = Math.Min(nodes1.Length, nodes2.Length); for (int i = 0; i < count; i++) { var node1 = nodes1[i]; var node2 = nodes2[i]; int cmp = CompareLongArrays(node1, node2); if (cmp != 0) { return(cmp); } } if (nodes1.Length > count) { return(1); } if (nodes2.Length > count) { return(-1); } return(0); }
/// <summary> /// Returns a child node of the parent. /// </summary> /// <param name="child1"> null or the hierarchyid of a child of the current node. </param> /// <param name="child2"> null or the hierarchyid of a child of the current node. </param> /// <returns> /// Returns one child node that is a descendant of the parent. /// If both child1 and child2 are null, returns a child of parent. /// If child1 is not null, and child2 is null, returns a child of parent greater than child1. /// If child2 is not null and child1 is null, returns a child of parent less than child2. /// If child1 and child2 are not null, returns a child of parent greater than child1 and less than child2. /// If child1 is not null and not a child of parent, an exception is raised. /// If child2 is not null and not a child of parent, an exception is raised. /// If child1 >= child2, an exception is raised. /// </returns> public HierarchyId GetDescendant(HierarchyId?child1, HierarchyId?child2) { if (child1 != null && (child1.Value.GetLevel() != GetLevel() + 1 || !child1.Value.IsDescendantOf(this))) { throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, GetDescendantMostBeChildExceptionMessage, "child1", child1, ToString()), "child1"); } if (child2 != null && (child2.Value.GetLevel() != GetLevel() + 1 || !child2.Value.IsDescendantOf(this))) { throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, GetDescendantMostBeChildExceptionMessage, "child2", child1, ToString()), "child2"); } if (child1 == null && child2 == null) { return(new HierarchyId(ToString() + 1 + PathSeparator)); } string hierarchyStr; if (child1 == null) { var result = new HierarchyId(child2.ToString()); var lastNode = result.GetNodes().Last(); //decrease the last part of the last node of the 1nd child lastNode[lastNode.Length - 1]--; hierarchyStr = PathSeparator + string.Join(PathSeparator, result.GetNodes().Select(LongArrayToString)) + PathSeparator; return(new HierarchyId(hierarchyStr)); } if (child2 == null) { var result = new HierarchyId(child1.ToString()); var lastNode = result.GetNodes().Last(); //increase the last part of the last node of the 2nd child lastNode[lastNode.Length - 1]++; hierarchyStr = PathSeparator + string.Join(PathSeparator, result.GetNodes().Select(LongArrayToString)) + PathSeparator; return(new HierarchyId(hierarchyStr)); } var child1LastNode = child1.Value.GetNodes().Last(); var child2LastNode = child2.Value.GetNodes().Last(); var cmp = CompareLongArrays(child1LastNode, child2LastNode); if (cmp >= 0) { throw new ArgumentException( string.Format(CultureInfo.InvariantCulture, GetDescendantChild1MustLessThanChild2ExceptionMessage, child1, child2), "child1"); } var newNode = GetBetween(child1LastNode, child2LastNode); hierarchyStr = PathSeparator + string.Join(PathSeparator, GetNodes().Select(LongArrayToString)) + PathSeparator + LongArrayToString(newNode) + PathSeparator; return(new HierarchyId(hierarchyStr)); }
/// <summary> /// Returns true if this is a descendant of parent. /// </summary> /// <returns>True if this is a descendant of parent.</returns> /// <param name="parent">parent</param> public bool IsDescendantOf(HierarchyId parent) { if (parent.GetLevel() > GetLevel()) { return(false); } for (int i = 0; i < parent.GetLevel(); i++) { int cmp = CompareLongArrays(GetNodes()[i], parent.GetNodes()[i]); if (cmp != 0) { return(false); } } return(true); }
public HierarchyId GetReparentedValue(HierarchyId oldRoot, HierarchyId newRoot) { if (!IsDescendantOf(oldRoot)) { throw new ArgumentException( string.Format(CultureInfo.InvariantCulture, GetReparentedValueOldRootExceptionMessage, oldRoot, ToString()), "oldRoot"); } StringBuilder sb = new StringBuilder(); sb.Append(PathSeparator); foreach (var node in newRoot.GetNodes()) { sb.Append(LongArrayToString(node)); sb.Append(PathSeparator); } foreach (var node in GetNodes().Skip(oldRoot.GetLevel())) { sb.Append(LongArrayToString(node)); sb.Append(PathSeparator); } return(new HierarchyId(sb.ToString())); }
/// <summary> /// Compares this instance to a given HierarchyId by their values. /// </summary> /// <param name="other"> the HierarchyId to compare against this instance </param> /// <returns> true if this instance is equal to the given HierarchyId, and false otherwise </returns> public bool Equals(HierarchyId other) => Compare(this, other) == 0;
/// <summary> /// Returns a child node of the parent. /// </summary> /// <param name="child1"> null or the hierarchyid of a child of the current node. </param> /// <param name="child2"> null or the hierarchyid of a child of the current node. </param> /// <returns> /// Returns one child node that is a descendant of the parent. /// If both child1 and child2 are null, returns a child of parent. /// If child1 is not null, and child2 is null, returns a child of parent greater than child1. /// If child2 is not null and child1 is null, returns a child of parent less than child2. /// If child1 and child2 are not null, returns a child of parent greater than child1 and less than child2. /// If child1 is not null and not a child of parent, an exception is raised. /// If child2 is not null and not a child of parent, an exception is raised. /// If child1 >= child2, an exception is raised. /// </returns> public HierarchyId GetDescendant(HierarchyId?child1, HierarchyId?child2) { if (child1 != null && (child1.Value.GetLevel() != GetLevel() + 1 || !child1.Value.IsDescendantOf(this))) { throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, GetDescendantMostBeChildExceptionMessage, "child1", child1, ToString()), "child1"); } if (child2 != null && (child2.Value.GetLevel() != GetLevel() + 1 || !child2.Value.IsDescendantOf(this))) { throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, GetDescendantMostBeChildExceptionMessage, "child2", child1, ToString()), "child2"); } if (child1 == null && child2 == null) { return(new HierarchyId(ToString() + 1 + PathSeparator)); } string hierarchyStr; if (child1 == null) { var result = new HierarchyId(child2.ToString()); var lastNode = result.GetNodes().Last(); //decrease the last part of the last node of the 1nd child lastNode[lastNode.Length - 1]--; hierarchyStr = PathSeparator + string.Join(PathSeparator, result.GetNodes().Select(IntArrayToString)) + PathSeparator; return(new HierarchyId(hierarchyStr)); } if (child2 == null) { var result = new HierarchyId(child1.ToString()); var lastNode = result.GetNodes().Last(); //increase the last part of the last node of the 2nd child lastNode[lastNode.Length - 1]++; hierarchyStr = PathSeparator + string.Join(PathSeparator, result.GetNodes().Select(IntArrayToString)) + PathSeparator; return(new HierarchyId(hierarchyStr)); } var child1LastNode = child1.Value.GetNodes().Last(); var child2LastNode = child2.Value.GetNodes().Last(); var cmp = CompareIntArrays(child1LastNode, child2LastNode); if (cmp >= 0) { throw new ArgumentException( string.Format(CultureInfo.InvariantCulture, GetDescendantChild1MustLessThanChild2ExceptionMessage, child1, child2), "child1"); } int firstDiffrenceIdx = 0; for (; firstDiffrenceIdx < child1LastNode.Length; firstDiffrenceIdx++) { if (child1LastNode[firstDiffrenceIdx] < child2LastNode[firstDiffrenceIdx]) { break; } } child1LastNode = child1LastNode.Take(firstDiffrenceIdx + 1).ToArray(); if (child1LastNode.Length >= firstDiffrenceIdx || child2LastNode.Length >= firstDiffrenceIdx) { child1LastNode = child1LastNode.Concat(new[] { 0 }).ToArray(); } else if (child1LastNode[firstDiffrenceIdx] + 1 < child2LastNode[firstDiffrenceIdx]) { child1LastNode[firstDiffrenceIdx]++; } else { child1LastNode = child1LastNode.Concat(new[] { 1 }).ToArray(); } hierarchyStr = PathSeparator + string.Join(PathSeparator, GetNodes().Select(IntArrayToString)) + PathSeparator + IntArrayToString(child1LastNode) + PathSeparator; return(new HierarchyId(hierarchyStr)); }