/// <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);
        }
예제 #2
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));
        }