Exemplo n.º 1
0
        internal int EnsureSelfAndChildrenNoLongerThan(int maxLength)
        {
            Contract.Requires <ArgumentOutOfRangeException>(maxLength > 0, "A path can only have a positive length.");
            Contract.Requires <ArgumentOutOfRangeException>(this.Parent == null || maxLength > this.Parent.FullLength + 1, "A child path cannot possibly be made shorter than its parent.");
            Contract.Ensures(Contract.Result <int>() <= maxLength);
            const int uniqueBase = 16;

            // Find the items that are too long, and always work on the longest one
            var         longPaths = this.SelfAndDescendents.Where(path => path.FullLength > maxLength).OrderByDescending(path => path.FullLength);
            PathSegment longPath;

            while ((longPath = longPaths.FirstOrDefault()) != null)
            {
                // Keep working on this one until it's short enough.
                do
                {
                    int         tooLongBy      = longPath.FullLength - maxLength;
                    var         longSegments   = longPath.SelfAndAncestors.Where(segment => !segment.minimized).OrderByDescending(segment => segment.CurrentName.Length);
                    PathSegment longestSegment = longSegments.FirstOrDefault();
                    if (longestSegment == null)
                    {
                        throw new InvalidOperationException("Unable to shrink path length sufficiently.");
                    }
                    PathSegment secondLongestSegment = longSegments.Skip(1).FirstOrDefault();
                    int         shortenByUpTo;
                    if (secondLongestSegment != null)
                    {
                        shortenByUpTo = Math.Min(tooLongBy, Math.Max(1, longestSegment.CurrentName.Length - secondLongestSegment.CurrentName.Length));
                    }
                    else
                    {
                        shortenByUpTo = tooLongBy;
                    }
                    int minimumGuaranteedUniqueLength = Math.Max(1, RoundUp(Math.Log(longestSegment.Siblings.Count(), uniqueBase)));
                    int allowableSegmentLength        = Math.Max(minimumGuaranteedUniqueLength, longestSegment.CurrentName.Length - shortenByUpTo);
                    if (allowableSegmentLength >= longestSegment.CurrentName.Length)
                    {
                        // We can't make this segment any shorter.
                        longestSegment.minimized = true;
                    }
                    longestSegment.currentName = longestSegment.CreateUniqueShortFileName(longestSegment.CurrentName, allowableSegmentLength);
                } while (longPath.FullLength > maxLength);
            }

            // Return the total length of self or longest child.
            return(this.SelfAndDescendents.Max(c => c.FullLength));
        }